《数据结构与算法分析》第十二章,K-d树,与配对堆简要介绍与实现

前言:

       这里我要介绍的这4个数据结构,是在《数据结构与算法分析》一书上的最后4种数据结构了。这些数据结构给出来了实现的代码,实现的难度并不大,一天之内我就把这四个数据结构的测试代码给调通了。

       这四个数据结构里,一个是红黑树的变种,对红黑树进行了化简,一个是为了多维查询范围所设计的数据结构。最后一个是变种的斐波那契堆,目的同样是为了化简实现。本来我想这几个数据结构就没必要再写了吧,后来想想。整个《数据结构与算法分析》这本书我都实现并写了博客,最后还是要做到有始有终吧。因为这几种数据结构的实现,对于我已经不再困难,主要是理解思想。因此在这里的介绍,主要还是介绍思想与展示一下调试的结果。

我的github:

我实现的代码全部贴在我的github中,欢迎大家去参观。

https://github.com/YinWenAtBIT

介绍:

K-d树:

一、特性:

在这里,我只实现了2-d树,查看别人的博客,发现Kd树会用来做邻近搜索等应用。不过在这里我只是简要介绍一下概念与实现,就不深入探讨这个问题了。

1.在奇数层按照第一个关键字排序,偶数层按照第二个关键字排序(同理可推出K个关键字的情况)

2.保持查找二叉树的性质,左小右大

二、编码实现:

由于这里只需要额外记录奇偶的层次,我们可以使用一个bool值对其反复取反即可。其他的操作等同于二叉查找树。

插入:

[cpp]  view plain copy
  1. KdTree insert(ElementType item, KdTree T)  
  2. {  
  3.     return insert(item, T, 0);  
  4. }  
  5.   
  6. KdTree insert(ElementType item, KdTree T, int level)  
  7. {  
  8.     if(T == NULL)  
  9.     {  
  10.         T = (KdTree)malloc(sizeof(struct KdNode));  
  11.         if(T == NULL)  
  12.             exit(1);  
  13.   
  14.         T->Element[0] = item[0];  
  15.         T->Element[1] = item[1];  
  16.         T->Priority  = rand()%Infinity;  
  17.         T->left = T->right = NULL;  
  18.   
  19.         return T;  
  20.     }  
  21.     else if(item[level] < T->Element[level])  
  22.         T->left = insert(item, T->left, !level);  
  23.     else   
  24.         T->right = insert(item, T->right);  
  25.   
  26.     return T;  
  27. }  
对于删除操作,由于涉及到多个层次,因此只使用懒惰删除。

三、范围查找:

这个功能就是Kd树的核心用处了。查找的方式其实也很简单,还是区分奇偶就行。

[cpp]  view plain copy
  1. /*打印范围*/  
  2. void PrintRange(ElementType Low, ElementType High , KdTree T)  
  3. {  
  4.     RecPrintRange(Low, High , T, 0);  
  5. }  
  6.   
  7. static void RecPrintRange(ElementType Low, ElementType High , KdTree T, int level)  
  8. {  
  9.     if(T != NULL)  
  10.     {  
  11.         if(Low[0] <= T->Element[0] && High[0] >= T->Element[0]   
  12.             && Low[1] <= T->Element[1] && High[1] >= T->Element[1])  
  13.                 printf("%d, %d\n", T->Element[0], T->Element[1]);  
  14.   
  15.   
  16.   
  17.         if(Low[level] <= T->Element[level])  
  18.             RecPrintRange(Low, High , T->left, !level);  
  19.   
  20.         if(High[level] >= T->Element[level])  
  21.             RecPrintRange(Low, High , T->right, !level);  
  22.     }  
  23. }  
测试:

《数据结构与算法分析》第十二章,K-d树,与配对堆简要介绍与实现_第1张图片

这里建立了2d树,然后查找15-60与20-60之间的数据。结果如上。

配对堆:

一、特性:

配对堆是一种比较实用的斐波那契堆,它的优势是在进行DecreaseKey的时候速度快于其他堆结构。

1.在这里,每个顶点可以接很多的孩子,在这里的实现类似与二项队列。使用左孩子与兄弟

2. 加了一个Prev指针,指向前向节点,可以指向父亲,也可以指向兄弟。

其实现如下图所示:




二、基础操作:

这里最基础的操作就是合并堆,由于一个根节点可以接许多的孩子,我们合并的时候,只需要让较小的根节点成为父亲,较大的根成为左孩子即可。


编码实现:

合并:

[cpp]  view plain copy
  1. PairHeap CompareAndLink(PairHeap H1, PairHeap H2)  
  2. {  
  3.     if(H2 == NULL)  
  4.         return H1;  
  5.     else if(H1 ->Element <= H2->Element)  
  6.     {  
  7.         H2->Prev = H1;  
  8.         H1->NextSibling = H2->NextSibling;  
  9.         if(H1->NextSibling != NULL)  
  10.             H1->NextSibling->Prev = H1;  
  11.   
  12.         H2->NextSibling = H1->Left;  
  13.         if(H2->NextSibling != NULL)  
  14.             H2->NextSibling->Prev = H2;  
  15.   
  16.         H1->Left = H2;  
  17.         return H1;  
  18.     }  
  19.     else  
  20.     {  
  21.         H2->Prev = H1->Prev;  
  22.         H1->Prev = H2;  
  23.         H1->NextSibling = H2->Left;  
  24.   
  25.         if(H1->NextSibling != NULL)  
  26.             H1->NextSibling->Prev = H1;  
  27.         H2->Left = H1;  
  28.         return H2;  
  29.     }  
  30.   
  31. }  

插入:

[cpp]  view plain copy
  1. PairHeap insert(ElementType X, PairHeap H, Position * Loc)  
  2. {  
  3.     PairHeap NewNode;  
  4.     NewNode = (PairHeap)malloc(sizeof(struct PairNode));  
  5.     if(NewNode == NULL)  
  6.         exit(1);  
  7.   
  8.     NewNode->Element = X;  
  9.     NewNode->Left = NewNode->NextSibling = NewNode ->Prev = NULL;  
  10.   
  11.     *Loc = NewNode;  
  12.     if(H == NULL)  
  13.         return NewNode;  
  14.   
  15.     return CompareAndLink(H, NewNode);  
  16. }  

删除:

[cpp]  view plain copy
  1. PairHeap deleteMin(ElementType * Min, PairHeap H)  
  2. {  
  3.     if(H == NULL)  
  4.         return H;  
  5.   
  6.     PairHeap NewRoot;  
  7.     *Min = H->Element;  
  8.     if(H->Left != NULL)  
  9.         NewRoot = CombineSiblings(H->Left);  
  10.     free(H);  
  11.   
  12.     return NewRoot;  
  13. }  

[cpp]  view plain copy
  1. PairHeap CombineSiblings(Position FirstSibling)  
  2. {  
  3.     static Position TreeArray[100];  
  4.     int i, j, Num;  
  5.   
  6.     if(FirstSibling == NULL)  
  7.         return FirstSibling;  
  8.   
  9.     for(Num =0; FirstSibling != NULL; Num++)  
  10.     {  
  11.         TreeArray[Num] = FirstSibling;  
  12.         FirstSibling->Prev->NextSibling = NULL;  
  13.         FirstSibling = FirstSibling->NextSibling;  
  14.     }  
  15.   
  16.     TreeArray[Num] = NULL;  
  17.   
  18.     for(i =0; i+1
  19.         TreeArray[i] = CompareAndLink(TreeArray[i], TreeArray[i+1]);  
  20.   
  21.   
  22.     j =i-2;  
  23.     if(j == Num -3)  
  24.         TreeArray[j] = CompareAndLink(TreeArray[j], TreeArray[j+2]);  
  25.   
  26.     for(; j>=2; j-=2)  
  27.         TreeArray[j-2] = CompareAndLink(TreeArray[j-2], TreeArray[j]);  
  28.   
  29.       
  30.   
  31.     return TreeArray[0];  
  32. }  

减小键值:

[cpp]  view plain copy
  1. PairHeap DecreaseKey(Position P, ElementType Delta, PairHeap H)  
  2. {  
  3.     if(Delta < 0)  
  4.         return H;  
  5.     P->Element -= Delta;  
  6.   
  7.     if(P == H)  
  8.         return H;  
  9.       
  10.     if(P->NextSibling != NULL)  
  11.         P->NextSibling->Prev = P->Prev;  
  12.   
  13.     if(P->Prev->Left == P)  
  14.         P->Prev ->Left = P->NextSibling;  
  15.     else  
  16.         P->Prev->NextSibling = P->NextSibling;  
  17.   
  18.     P->NextSibling = NULL;  
  19.     return CompareAndLink(H, P);  
  20. }  

测试:

《数据结构与算法分析》第十二章,K-d树,与配对堆简要介绍与实现_第2张图片《数据结构与算法分析》第十二章,K-d树,与配对堆简要介绍与实现_第3张图片

左图是插入节点之后,形成的配对堆,可见,只有0是根,其他的都是孩子。

右图是删除根节点0之后,形成的新配对堆。

总结:

到这里,整个《数据结构与算法分析》上的数据结构与算法,就算是全部都学习完了,学习的收获非常大,我会写一篇新的感想博客来好好说说。

你可能感兴趣的:(数据结构)