二叉堆 - 最大堆

与上篇《二叉堆 - 最小堆》类似,只不过堆序(heap order)从内部节点小于左右子节点变成了内部节点大于左右子节点。

代码如下:

  1 #include <cstdio>
  2 #include <cstdlib>
  3 
  4 #define MIN (1<<(sizeof(int)*8-1))
  5 #define MAX (~MIN)
  6 
  7 typedef int Item;
  8 typedef struct HeapStruct* heap;
  9 
 10 struct HeapStruct {
 11     int capacity;  // capacity的大小为堆的元素加1。 
 12     int size;      // size指向堆中最后一个元素,size=0时堆为空 
 13     Item* items;   // items的第一个元素存放sentinel,其余元素存放堆中内容。 
 14 };
 15 // 初始化堆的三个参数 
 16 heap
 17 InitHeap(int maxItems)
 18 {
 19     heap h;
 20     
 21     h = (heap)malloc(sizeof(struct HeapStruct));
 22     if (h == NULL) {
 23         printf("out of space.\n");
 24         return NULL;
 25     }
 26     
 27     h->items =(Item*)malloc((maxItems+1)*sizeof(Item)); // 用h->items[0]来存放sentinel 
 28     if (h->items == NULL) {
 29         printf("out of space.\n");
 30         return NULL;
 31     }
 32     
 33     h->capacity = maxItems;
 34     h->size = 0;
 35     h->items[0] = MAX;
 36     
 37     return h;
 38 }
 39   
 40 int
 41 IsFull(heap h)
 42 {
 43     if (h->size == h->capacity) {
 44         return 1;
 45     } else {
 46         return 0;
 47     }
 48 }
 49 
 50 int
 51 IsEmpty(heap h)
 52 {
 53     if (h->size == 0) {
 54         return 1;
 55     } else {
 56         return 0;
 57     }
 58 }
 59   
 60 Item
 61 FindMax(heap h)
 62 {
 63     return h->items[1];
 64 }
 65 // 向最大堆插入元素。  
 66 void
 67 Insert(Item item, heap h)
 68 {
 69     if (IsFull(h)) {
 70         printf("Insert failed. Because the heap is full.\n");
 71         return;
 72     }
 73     // percolate up,将item往上,一步一步放到合适的地方。
 74     int i; 
 75     for (i = ++h->size; h->items[i/2] < item; i /= 2) {
 76         h->items[i] = h->items[i/2];
 77     }
 78     h->items[i] = item;
 79 }
 80 // 在最大堆中删除元素。 返回最大值。 
 81 Item
 82 DeleteMax(heap h)
 83 {
 84     if (IsEmpty(h)) {
 85         printf("Delete failed. Because the heap is empty.\n");
 86         return h->items[0];
 87     }
 88     
 89     Item maxItem = h->items[1];
 90     Item lastItem = h->items[h->size--]; // 此函数目的就是把lastItem放到合适位置 
 91     // percolate down,将lastItem往下,一步一步往下寻找合适的地方。
 92     int i, child;
 93     for (i = 1; 2*i <= h->size; i = child) {
 94         child = 2 * i;
 95         // 将child放在左右子树中较大的那个位置上
 96         if (child != h->size && h->items[child] < h->items[child+1]) {
 97             child++;
 98         }
 99         
100         if (lastItem < h->items[child]) {
101             h->items[i] = h->items[child];
102         } else {
103             break;
104         }
105     }
106     h->items[i] = lastItem;
107     return maxItem;
108 }
109 // 以插入的方式来建堆。复杂度为O(NlogN),因为有N个元素,每次插入花费logN时间。      
110 void
111 BuildHeap(heap h, Item arr[], int len)
112 {
113     for (int i = 0; i < len; i++) {
114         Insert(arr[i], h);
115     }
116 }
117 // 以下滤的方式来建堆(对已有的数组进行排序,使之符合最大堆的堆序heap order)。
118 // 参数i为数组对应的二叉堆的内部节点,下滤操作将之放到比左右子节点都大的位置上。 
119 void
120 PercDown(heap h, int i) 
121 {
122     int child;
123     int tmp;
124     
125     for (tmp = h->items[i]; 2*i <= h->size; i = child) {
126         child = 2*i;
127         if (child != h->size && h->items[child] < h->items[child+1]) {
128             child++;
129         }
130         if (tmp < h->items[child]) {
131             h->items[i] = h->items[child];
132         } else {
133             break;
134         }
135     }
136     h->items[i] = tmp;
137 }         
138 
139 int 
140 main(int argc, char** argv)
141 {
142     int arr[6] = {17, 11, 2, 23, 5, 7};
143     
144     heap h;
145     h = InitHeap(6);
146     //BuildHeap(h, arr, 6);
147     
148     // build heap
149     for (int i = 0; i < 6; i++) {
150         h->items[++h->size] = arr[i];
151         
152     }
153     for (int i = 6/2; i > 0; i--) {
154         PercDown(h, i);
155     }
156     
157     for (int i = 1; i <= h->size; i++) {
158         printf("%d\t", h->items[i]);
159     }
160     printf("\n");
161     
162     // test DeleteMin, out put a sorted array
163     int sortedArr[6] = {0};
164     for (int i = 0; i < 6; i++) {
165         sortedArr[i] = DeleteMax(h);
166     }
167     for (int i = 0; i < 6; i++) {
168         printf("%d\t", sortedArr[i]);
169     }
170     printf("\n");
171     
172     system("pause");
173     
174     return 0;
175 }

 

posted @ 2014-10-29 15:31  nipan  阅读(287)  评论(0编辑  收藏  举报