郑重声明:本文99.99%转载自http://blog.csdn.net/morewindows/article/details/6709644/
快一年没碰堆排序了……在这里给自己 总结 搞晕一下。
*堆排序基于二叉堆
-
二叉堆的定义
二叉堆是完全二叉树或者是近似完全二叉树。
二叉堆满足二个特性:
1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
- 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。下图展示一个最小堆:
- 由于其它几种堆(二项式堆,斐波纳契堆等)用的较少,一般将二叉堆就简称为堆。
- 一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。上图:
-
堆的插入、删除
- 堆的插入:
1 // 新加入i结点 其父结点为(i - 1) / 2 2 void MinHeapFixup(int a[], int i) 3 { 4 int j, temp; 5 6 temp = a[i]; 7 j = (i - 1) / 2; //父结点 8 while (j >= 0 && i != 0) 9 { 10 if (a[j] <= temp) 11 break; 12 13 a[i] = a[j]; //把较大的子结点往下移动,替换它的子结点 14 i = j; 15 j = (i - 1) / 2; 16 } 17 a[i] = temp; 18 }
- 堆的删除:
代码和以上类似,就不赘述了。但是要注意:堆的插入是从下至上,堆的删除是从上至下!堆的删除要寻找子节点中最小或最大的节点,与其替换,重复这个步骤直至自己在子节点中最小。这样,堆才是可维护的。
以上是对堆的基础知识与操作。下面是堆排序的流程
-
堆化数组(堆排序第一步)
堆化数组只有一个方法——对堆中的元素进行向下调整(类似于堆的删除,只不过把根节点换成了普通节点)。而且调整的顺序是从下至上!!!
这就相当于把更大(或更小)的数据换了上来,一直换到堆的最上方。而那些次要的数据就被留在下面。
实现代码:
1 //建立最小堆 2 void MakeMinHeap(int a[], int n) 3 { 4 for (int i = n / 2 - 1; i >= 0; i--) 5 MinHeapFixdown(a, i, n); 6 }
-
堆交换(堆排序第二步)
每次提取堆的根节点,然后对堆进行一次删除操作。这样可把次大的节点换上来……
1 void MinheapsortTodescendarray(int a[], int n) 2 { 3 for (int i = n - 1; i >= 1; i--) 4 { 5 Swap(a[i], a[0]); 6 MinHeapFixdown(a, 0, i); 7 } 8 }
這樣就夶功告成叻
(当然还要输出啦^(* ̄(oo) ̄)^)
╭︿︿︿╮
{/ o o /}
( (oo) )
︶ ︶︶ {The king of the pig}
时间: 2024-10-12 17:58:16