1,堆排序
概念
堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2
堆的插入与删除
堆的插入:每次插入都是将新数据放在数组最后
堆的删除:
按定义,堆中每次都只能删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。
堆排序:
首先可以看到堆建好之后堆中第0个数据是堆中最小的数据。取出这个数据再执行下堆的删除操作。
这样堆中第0个数据又是堆中最小的数据,重复上述步骤直至堆中只有一个数据时就直接取出这个数据。
- 建堆过程C语言表示:
- 1: /*
- 2: 输入:数组A,堆的长度hLen,以及需要调整的节点i
- 3: 功能:调堆
- 4: */
- 5:
- 6: void AdjustHeap(int A[], int hLen, int i)
- 7: {
- 8: int left = LeftChild(i); //节点i的左孩子
- 9: int right = RightChild(i); //节点i的右孩子节点
- 10: int largest = i;
- 11: int temp;
- 12:
- 13: while(left < hLen || right < hLen)
- 14: {
- 15: if (left < hLen && A[largest] < A[left])
- 16: {
- 17: largest = left;
- 18: }
- 19:
- 20: if (right < hLen && A[largest] < A[right])
- 21: {
- 22: largest = right;
- 23: }
- 24:
- 25: if (i != largest) //如果最大值不是父节点
- 26: {
- 27: temp = A[largest]; //交换父节点和和拥有最大值的子节点交换
- 28: A[largest] = A[i];
- 29: A[i] = temp;
- 30:
- 31: i = largest; //新的父节点,以备迭代调堆
- 32: left = LeftChild(i); //新的子节点
- 33: right = RightChild(i);
- 34: }
- 35: else
- 36: {
- 37: break;
- 38: }
- 39: }
- 40: }
- 41:
- 42: /*
- 43: 输入:数组A,堆的大小hLen
- 44: 功能:建堆
- 45: */
- 46: void BuildHeap(int A[], int hLen)
- 47: {
- 48: int i;
- 49: int begin = hLen/2 - 1; //最后一个非叶子节点
- 50: for (i = begin; i >= 0; i--)
- 51: {
- 52: AdjustHeap(A, hLen, i);
- 53: }
- 54: }
- 55:
- 56: /*
- 57: 输入:数组A,待排序数组的大小aLen
- 58: 功能:堆排序
- 59: */
- 60: void HeapSort(int A[], int aLen)
- 61: {
- 62: int hLen = aLen;
- 63: int temp;
- 64:
- 65: BuildHeap(A, hLen); //建堆
- 66:
- 67: while (hLen > 1)
- 68: {
- 69: temp = A[hLen-1]; //交换堆的第一个元素和堆的最后一个元素
- 70: A[hLen-1] = A[0];
- 71: A[0] = temp;
- 72: hLen--; //堆的大小减一
- 73: AdjustHeap(A, hLen, 0); //调堆
- 74: }
- 75: }