Fork me on GitHub

数据结构与算法——堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特 点快速定位指定索引的元素.

(选择排序工作原理 - 第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置, 然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待 排序的数据元素的个数为零)

 

1. 排序核心实现

 

 

2. 具体算法实现

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 typedef struct _Heap 
  6 {
  7 int *arr; //存储堆元素的数组
  8 int size; //当前已存储的元素个数
  9 int capacity; //当前存储的容量
 10 }Heap;
 11 
 12 bool initHeap(Heap &heap, int *orginal, int size);
 13 bool popMax(Heap &heap, int &value);
 14 void heapSort(Heap &heap);
 15 static void buildHeap(Heap &heap);
 16 static void adjustDown(Heap &heap, int index);
 17 
 18 /*初始化堆*/
 19 bool initHeap(Heap &heap, int *orginal, int size) 
 20 {
 21     //heap.arr = new int[capacity];
 22     heap.arr = orginal;
 23     if (!heap.arr) return false;
 24     
 25     heap.capacity = size;
 26     heap.size = size;
 27     
 28     //如果存在原始数据则构建堆
 29     if(size > 0)
 30     {
 31         //方式一: 直接调整所有元素
 32         //建堆
 33         buildHeap(heap);
 34     }
 35     return true;
 36 }
 37 
 38 /* 从最后一个父节点(size/2-1 的位置)逐个往前调整所有父节点(直到根节点), 确保每一个父节点都是一个最大堆,最后整体上形成一个最大堆 */
 39 void buildHeap(Heap &heap) 
 40 {
 41     int i;
 42     for (i = heap.size / 2 - 1; i >= 0; i--) 
 43     {
 44         adjustDown(heap, i);
 45     }
 46 }
 47 
 48 /*将当前的节点和子节点调整成最大堆*/
 49 void adjustDown(Heap &heap, int index)
 50 {
 51     int cur = heap.arr[index];            //当前待调整的节点
 52     int parent, child;
 53     
 54     /*判断否存在大于当前节点子节点,如果不存在 ,则堆本身是平衡的,不需要调整;
 55     如果存在,则将最大的子节点与之交换,交换后,如果这个子节点还有子节点,则要继续
 56     按照同样的步骤对这个子节点进行调整*/
 57     for (parent = index; (parent * 2 + 1)<heap.size; parent = child) 
 58     {
 59         child = parent * 2 + 1;
 60         //取两个子节点中的最大的节点
 61         if (((child + 1)<heap.size) && (heap.arr[child]<heap.arr[child + 1])) 
 62         {
 63             child++;
 64         }
 65         //判断最大的节点是否大于当前的父节点
 66         if (cur >= heap.arr[child]) 
 67         {
 68             //不大于,则不需要调整,跳出循环
 69             break;
 70         }
 71         else 
 72         {
 73             //大于当前的父节点,进行交换,然后从子节点位置继续向下调整
 74             heap.arr[parent] = heap.arr[child];
 75             heap.arr[child] = cur;
 76         }
 77     }
 78 }
 79 
 80 /* 实现堆排序 */
 81 void heapSort(Heap &heap)
 82 {
 83     if (heap.size<1) return ;
 84     while(heap.size>0)
 85     {
 86         int tmp = heap.arr[0];
 87         heap.arr[0] = heap.arr[heap.size-1];
 88         heap.arr[heap.size-1] = tmp;
 89         heap.size--;
 90         adjustDown(heap, 0);// 向下执行堆调整
 91     }
 92 }
 93 
 94 /* 删除最大的节点,并获得节点的值*/
 95 bool popMax(Heap &heap, int &value) 
 96 {
 97     if (heap.size<1) return false;
 98     value = heap.arr[0];
 99     heap.arr[0] = heap.arr[--heap.size];
100     //heap.arr[0] = heap.arr[heap.size-1];
101     //heap.size--;
102     adjustDown(heap, 0);// 向下执行堆调整
103     return true;
104 }
105 
106 int main(void) 
107 {
108     Heap hp;
109     int origVals[] = { 1, 2, 3, 87, 93, 82, 92, 86, 95 };
110     int i = 0;
111     if(!initHeap(hp, origVals, sizeof(origVals)/sizeof(origVals[0])))
112     {
113         fprintf(stderr, "初始化堆失败!\n");
114         exit(-1);
115     }
116     
117     for (i = 0; i<hp.size; i++) 
118     {
119         printf("the %dth element:%d\n", i, hp.arr[i]);
120     }
121     
122     //执行堆排序
123     heapSort(hp);
124     printf("堆排序后的结果:\n");
125     for(i=0; i<sizeof(origVals)/sizeof(origVals[0]); i++)
126     {
127         printf(" %d", origVals[i]);
128     }
129     
130     system("pause");
131     return 0;
132 }

 

 

3. 快速查找无序集合中前 N 大(小)的记录

 

posted @ 2020-10-18 22:15  索智源  阅读(113)  评论(0编辑  收藏  举报