1. 堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。
二叉堆的定义
二叉堆是完全二叉树或者是近似完全二叉树。
二叉堆满足二个特性:
1)父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2)每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆
堆分为大顶堆和小顶堆,其中下图(1)中是大顶堆,(2)为小顶堆
C6NF_O.jpg)
2. 堆排序的思想
利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。
其基本思想为(大顶堆):
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
下面举例说明(大顶堆):
给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。
1)首先根据该数组元素构建一个完全二叉树,得到



20和16交换后导致16不满足堆的性质,因此需重新调整
这样就得到了初始堆。
此时3位于堆顶不满堆的性质,则需调整继续调整






其实就是每次把堆顶元素和最后没交换过的子节点元素交换,然后将此子节点之前的二叉树重新排序,变成大顶堆。
如果按递增排序,需要用到大顶堆,每次把堆顶(无序堆最大值)放到有序堆前面,重新得到无序区大顶堆;
如果按递减排序,需要用到小顶堆,每次把堆顶(无序堆最小值)放到有序堆前面,重新得到无序区小顶堆;
程序如下(包含递增和递减):
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6
7 namespace conHeapSort
8 {
9 class HeapSort
10 {
11 private static Boolean Asce = true;//heap sorted by ascending order
12 private static Boolean Desc = false;//heap sorted by descending order
13 static void Main(string[] args)
14 {
15 List<int> input = new List<int>();
16 HeapSort exap = new HeapSort();
17 String str;
18
19 input.Add(0);//start from index one
20 str = Console.ReadLine();
21 while(str != "exit"){
22 input.Add(Int32.Parse(str));
23 str = Console.ReadLine();
24 }
25
26 exap.SortHeap(input, Desc);
27 for (int i = 1; i < input.Count; i++ )
28 {
29 Console.WriteLine(input[i].ToString());
30 }
31 }
32 void SortHeap(List<int> data, Boolean order)
33 {
34 BuildHeap(data, order);
35
36 if (order)
37 {
38 for (int i = data.Count - 1; i >= 1; i--)
39 {
40 Swap(data, 1, i); //exchange between index 1 and index i
41 MaxHeap(data, 1, i - 1); //get max heap
42 }
43 }
44 else
45 {
46 for (int i = data.Count - 1; i >= 1; i--)
47 {
48 Swap(data, 1, i);//exchange between index 1 and index i
49 MinHeap(data, 1, i - 1); //get min heap
50 }
51 }
52 }
53 void BuildHeap(List<int> data, Boolean order)
54 {
55 if (order) //make maximal heap
56 {
57 for (int i = data.Count / 2; i >= 1; i--)
58 {
59 MaxHeap(data, i, data.Count - 1); //initialize
60 }
61 }
62 else //make minimal heap
63 {
64 for (int i = data.Count / 2; i >= 1; i--)
65 {
66 MinHeap(data, i, data.Count - 1);//initialize
67 }
68 }
69 }
70 //get max heap
71 void MaxHeap(List<int> data, int i, int size)
72 {
73 int lchild = 2 * i;
74 int rchild = lchild + 1;
75 int max = i;
76 if (i <= size / 2)
77 {
78 if (lchild <= size && data[lchild] > data[max])
79 {
80 max = lchild;
81 }
82 if (rchild <= size && data[rchild] > data[max])
83 {
84 max = rchild;
85 }
86 if (max != i)
87 {
88 Swap(data, i, max); //exchange child and parent node
89 MaxHeap(data, max, size); //continue to adjust
90 }
91 }
92 }
93 //get min heap
94 void MinHeap(List<int> data, int i, int size)
95 {
96 int lchild = 2 * i;
97 int rchild = lchild + 1;
98 int min = i;
99 if (i <= size / 2)
100 {
101 if (lchild <= size && data[lchild] < data[min])
102 {
103 min = lchild;
104 }
105 if (rchild <= size && data[rchild] < data[min])
106 {
107 min = rchild;
108 }
109 if (min != i)
110 {
111 Swap(data, i, min);//exchange child and parent node
112 MinHeap(data, min, size);
113 }
114 }
115 }
116 //exchange index1 and index2 in data
117 void Swap(List<int> data, int index1, int index2)
118 {
119 int temp = data[index2];
120 data[index2] = data[index1];
121 data[index1] = temp;
122 }
123 }
124 }
来源:https://www.cnblogs.com/ywl925/archive/2013/01/22/2870474.html