数据结构与算法——堆 特点与算法实现(一)
1. 堆的特点:
1.1. 每个节点最多可以有两个节点
1.2. 根节点的键值是所有堆节点键值中最大者(如果是最小堆则相反),且每个节点的值都比其两个或一个子节点的值大(如果是最小堆则相反)
1.3. 除了根节点没有兄弟节点,最后一个左子节点可以没有兄弟节点,其他节点必须有兄弟节点
2. 堆的结构:
堆是你见过的最有个性的树!它是用数组表示的树
在数组中快速创建堆
2.1. 首先我们需要找到最后一个结点的父结点如图(a),我们找到的结点是 87,然后找出该结点的最大子节点与自 己比较,若该子节点比自身大,则将两个结点交换. 图(a)中,87 比左子节点 95 小,则交换之.如图(b)所示
2.2. 我们移动到前一个父结点 93,如图(c)所示.同理做第一步的比较操作8,结97果9不43需8要40交1换
3.继续移动结点到前一个父结点 82,如图(d)所示,82 小于右子节点 95,则 82 与 95 交换,如图(e)所示,82 交换 后,其值小于左子节点,不符合最大堆的特点,故需要继续向下调整,如图(f)所示
4.所有节点交换完毕,最大堆构建完成
3. 堆的算法实现
堆数据结构的定义
1 #define DEFAULT_CAPCITY 128 2 3 typedef struct _Heap 4 { 5 int *arr; //存储堆元素的数组 6 int size; //当前已存储的元素个数 7 int capacity; //当前存储的容量 8 }Heap;
建(最大)堆
1 bool initHeap(Heap &heap, int *orginal, int size); 2 static void buildHeap(Heap &heap); 3 static void adjustDown(Heap &heap, int index); 4 5 /*初始化堆*/ 6 bool initHeap(Heap &heap, int *orginal, int size) 7 { 8 int capacity = DEFAULT_CAPCITY>size? DEFAULT_CAPCITY:size; 9 10 heap.arr = new int[capacity]; 11 if(!heap.arr) return false; 12 13 heap.capacity = capacity; 14 heap.size = 0; 15 16 //如果存在原始数据则构建堆 17 if(size>0) 18 { 19 memcpy(heap.arr, orginal, size*sizeof(int)); 20 heap.size = size; 21 buildHeap(heap); 22 } 23 else 24 { 25 heap.size = 0; 26 } 27 return true; 28 } 29 30 /*将当前的节点和子节点调整成最大堆*/ 31 void adjustDown(Heap &heap, int index) 32 { 33 int cur=heap.arr[index]; //当前待调整的节点 34 int parent,child; 35 36 /*判断否存在大于当前节点子节点,如果不存在 ,则堆本身是平衡的,不需要调整; 37 如果存在,则将最大的子节点与之交换,交换后,如果这个子节点还有子节点, 38 则要继续按照同样的步骤对这个子节点进行调整*/ 39 for(parent=index; (parent*2+1)<heap.size; parent=child) 40 { 41 child=parent*2+1; 42 //取两个子节点中的最大的节点 43 if(((child+1)<heap.size)&&(heap.arr[child]<heap.arr[child+1])) 44 { 45 child++; 46 } 47 //判断最大的节点是否大于当前的父节点 48 if(cur>=heap.arr[child]) 49 { 50 //不大于,则不需要调整,跳出循环 51 break; 52 } 53 else 54 { 55 //大于当前的父节点,进行交换,然后从子节点位置继续向下调整 56 heap.arr[parent]=heap.arr[child]; 57 heap.arr[child]=cur; 58 } 59 } 60 } 61 62 /* 从最后一个父节点(size/2-1 的位置)逐个往前调整所有父节点(直到根节点), 63 确保每一个父节点都是一个最大堆,最后整体上形成一个最大堆 */ 64 void buildHeap(Heap &heap) 65 { 66 int i; 67 for(i=heap.size/2-1; i>=0; i--) 68 { 69 adjustDown(heap, i); 70 } 71 }