堆排序-HeapSort

1. 堆排序快速排序归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。

二叉堆的定义

二叉堆是完全二叉树或者是近似完全二叉树。

二叉堆满足二个特性:

 1)父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

 2)每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆

堆分为大顶堆和小顶堆,其中下图(1)中是大顶堆,(2)为小顶堆

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)首先根据该数组元素构建一个完全二叉树,得到

 
 2)然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:

20和16交换后导致16不满足堆的性质,因此需重新调整

这样就得到了初始堆。

即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。
3)

此时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 }

 

posted @ 2013-01-22 10:17  ywl925  阅读(451)  评论(0编辑  收藏  举报
Copyright at 2012 yangwenlong