alex_bn_lee

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

【425】堆排序方法(二叉堆)优先队列(PQ)

参考:漫画:什么是二叉堆?

  • 大根堆
  • 小根堆

参考:漫画:什么是堆排序?

参考:漫画:什么是优先队列?

参考:【video】视频--第14周10--第8章排序10--8.4选择排序3--堆排序2--堆调整


堆的调整(小根堆)

  • 输出堆顶元素之后,以堆中最后一个元素替代之;
  • 然后将根节点值与左、右子树的根节点值进行比较,并与其中小者进行交换;
  • 重复上述操作,直至叶子节点,将得到新的堆,称这个从堆顶至叶子的调整过程为“筛选”。

大根堆与上面类似。

通过3中方法实现ADT:

  • 堆的形式
  • 无序array
  • 有序array

第一步:一组数据

  如下图:

第二步:构建完全二叉树

第三步:构建大根堆

  从 last_child/2 节点往前,每个节点与其子节点比较,按照 fixDown 操作,如下图:

第四步:pop 最大值

  执行 delMax 操作,将最大值输出,然后将最后的节点编程根节点,然后执行 fixDown 操作,如下图:

参考:HEAP SORT

代码实现如下:

pq.h

1
2
3
4
5
6
7
8
9
10
// pq.h: ADT interface for a priority queue
#include <stdio.h>
#include <stdlib.h>
 
typedef struct pqRep *PQ;
 
PQ   createPQ(int size);
void insertPQ(PQ q, int it);
int  delMaxPQ(PQ q);
int  isEmptyPQ(PQ q);

pqSort.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* pqSort.c: use a priority queue to sort an array of integers
             into descending order
 */
#include "pq.h"
 
int main() {
   int a[] = {41, 2, 58, 156, 360, 81, 260, 74, 167, 13};
   int length = sizeof(a)/sizeof(a[0]);
 
   PQ q = createPQ(length);
   printf("Array: ");
   for (int i = 0; i < length; i++) {
       printf("%d ", a[i]);
       insertPQ(q, a[i]);
   }
   printf("\nSorted: ");
   while (!isEmptyPQ(q)) {
       printf("%d ", delMaxPQ(q));
   }
   putchar('\n');
   return EXIT_SUCCESS;
}

pqHP.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// pqHP.c: priority queue implementation for pq.h using a heap
#include "pq.h"
 
// 'static' means these functions are for local use only
static void fixDown(int *, int, int);
static void fixUp(int *, int);
 
// Priority queue implementation using an unordered array
struct pqRep {
   int nItems;  // actual count of Items
   int *items;  // array of Items
   int maxsize; // maximum size of array
};
 
PQ createPQ(int size) {
   PQ q = malloc(sizeof(struct pqRep));  // make room for the structure
   if (q == NULL) {
      fprintf(stderr, "out of memory\n");
      exit(0);
   }
   q->items = malloc((size+1) * sizeof(int)); // make room for the array
   if (q->items == NULL) {                // size+1 because heap 1..size
      fprintf(stderr, "out of memory\n");
      exit(0);
   }
   q->nItems = 0;                          // we have no items yet
   q->maxsize = size;                      // remember the maxsize
   return q;                               // return the initial PQ
}
 
void insertPQ(PQ q, int it) {
    if (q == NULL) {
       fprintf(stderr, "priority queue not initialised\n");
       exit(1);
    }
    if (q->nItems == q->maxsize) {
       fprintf(stderr, "priority queue full\n");
       exit(1);
    }
    q->nItems++;                    // adding another item
    q->items[q->nItems] = it;       // put the item at the end
    fixUp(q->items, q->nItems);     // fixUp all the way to the root
    return;
}
 
int delMaxPQ(PQ q) {
   if (q == NULL) {
      fprintf(stderr, "priority queue not initialised\n");
      exit(1);
   }
   if (q->nItems == 0) {
      fprintf(stderr, "priority queue empty\n");
      exit(1);
   }
   int retval = q->items[1];          // this is the item we want to return
   q->items[1] = q->items[q->nItems]; // overwrite root by last item
   q->nItems--;                       // we are decreasing heap size by 1
   fixDown(q->items, 1, q->nItems);   // fixDown the new root
   return retval;
}
 
int isEmptyPQ(PQ q) {
   int empty = 0;
   if (q == NULL) {
      fprintf(stderr, "isEmptyPQ: priority queue not initialised\n");
   }
   else {
      empty = q->nItems == 0;
   }
   return empty;
}
 
// fix up the heap for the 'new' element child
void fixUp(int *heap, int child) {
   while (child>1 && heap[child/2]<heap[child]) {
      int swap = heap[child];         // if parent < child, do a swap
      heap[child] = heap[child/2];
      heap[child/2] = swap;
      child = child/2;                // become the parent
   }
   return;
}
 
// force value at a[par] into correct position
void fixDown(int *heap, int par, int len) {
   int finished = 0;
   while (2*par<=len && !finished) {// as long as you are within bounds
      int child = 2*par;          // the first child is here
      if (child<len && heap[child]<heap[child+1]) {
         child++;                 // choose larger of two children
      }
      if (heap[par]<heap[child]) { // if node is smaller than this child ...
         int swap = heap[child];   // if parent < child, do a swap
         heap[child] = heap[child/2];
         heap[child/2] = swap;
         par = child;             // ... and become this child
      }
      else {
         finished = 1;            // else we do not have to go any further
      }
   }
   return;
}

Compile and run:

1
2
3
4
prompt$ dcc pqHP.c pqSort.c
prompt$ ./a.out
Array: 41 2 58 156 360 81 260 74 167 13
Sorted: 360 260 167 156 81 74 58 41 13 2

通过array来实现ADT,就是每次通过遍历比array里面的最大值,然后输出,并由最后一个元素补位

pqUA.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// pqUA.c: priority queue implementation for pq.h using an unordered array
#include "pq.h"
 
struct pqRep {
   int nItems;  // actual count of Items
   int *items;  // array of Items
   int maxsize; // maximum size of array
};
 
PQ createPQ(int size) {
   PQ q = malloc(sizeof(struct pqRep));  // make room for the structure
   if (q == NULL) {
      fprintf(stderr, "out of memory\n");
      exit(0);
   }
 
   q->items = malloc(size * sizeof(int)); // make room for the array
   if (q->items == NULL) {
      fprintf(stderr, "out of memory\n");
      exit(0);
   }
   q->nItems = 0;                          // we have no items yet
   q->maxsize = size;                      // remember the maxsize
   return q;                               // return the initial PQ
}
 
void insertPQ(PQ q, int it) {
    if (q == NULL) {
       fprintf(stderr, "priority queue not initialised\n");
       exit(1);
    }
    if (q->nItems == q->maxsize) {
       fprintf(stderr, "priority queue full\n");
       exit(1);
    }
    q->items[q->nItems] = it; // UNORDERED ARRAY, so put item at the end
    q->nItems++;              // increment the 'counter'
}
 
int delMaxPQ(PQ q) { // UNORDERED, so need to linear search for max item
    if (q == NULL) {
       fprintf(stderr, "delmaxPQ: priority queue not initialised\n");
       exit(1);
    }
    if (q->nItems == 0) {
       fprintf(stderr, "priority queue empty\n");
       exit(1);
    }
    int *array = q->items;
    int last = q->nItems-1;        // items occupy places 0 .. last
    int max = 0;                   // assume initially item at max=0 has largest key
    for (int i = 1; i <= last; i++){
       if (array[max] < array[i]){ // now compare with every other item
          max = i;                 // whenever we find a better one, update max
       }
    }   
    int retval = array[max];       // save the max item
    array[max] = array[last];      // overwrite max location with last item
    q->nItems--;                   // decrease the number of items
    return retval;                 // return the max element
}
 
int isEmptyPQ(PQ q) {
   int empty = 0;
   if (q == NULL) {
      fprintf(stderr, "isEmptyPQ: priority queue not initialised\n");
   }
   else {
      empty = q->nItems == 0;
   }
   return empty;
}

也可以通过有序array来实现,就是在插入的过程中就进行排序

pqOA.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// pqOA.c: priority queue implementation for pq.h using an ordered array
#include "pq.h"
 
struct pqRep {
   int nItems;  // actual count of Items
   int *items;  // array of Items
   int maxsize; // maximum size of array
};
 
PQ createPQ(int size) {
   PQ q = malloc(sizeof(struct pqRep));  // make room for the structure
   if (q == NULL) {
      fprintf(stderr, "out of memory\n");
      exit(0);
   }
   q->items = malloc(size * sizeof(int)); // make room for the array
   if (q->items == NULL) {
      fprintf(stderr, "out of memory\n");
      exit(0);
   }
   q->nItems = 0;                          // we have no items yet
   q->maxsize = size;                      // remember the maxsize
   return q;                               // return the initial PQ
}
 
void insertPQ(PQ q, int it) {
    if (q == NULL) {
       fprintf(stderr, "priority queue not initialised\n");
       exit(1);
    }
    if (q->nItems == q->maxsize) {
       fprintf(stderr, "priority queue full\n");
       exit(1);
    }
    int *array = q->items;
    int last = q->nItems;
    int i;
    for (i=0; i<last && array[i]<it; i++) {
        ;                      // find location of item == it
    }
    int j;
    for (j = last; j>i; j--){  // starting at last and go down to i
        array[j] = array[j-1]; // shift items up
    }
    array[i] = it;             // now insert item 'it' at i
    q->nItems++;               // increase the count
}
 
int delMaxPQ(PQ q) {
    if (q == NULL) {
       fprintf(stderr, "priority queue not initialised\n");
       exit(1);
    }
    if (q->nItems == 0) {
       fprintf(stderr, "priority queue empty\n");
       exit(1);
    }
    q->nItems--;
    return q->items[q->nItems];
}
 
int isEmptyPQ(PQ q) {
   int empty = 0;
   if (q == NULL) {
      fprintf(stderr, "isEmptyPQ: priority queue not initialised\n");
   }
   else {
      empty = q->nItems == 0;
   }
   return empty;
}

 

posted on   McDelfino  阅读(600)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示