堆排序-HeapSort
2013-01-22 10:17
330 查看
1. 堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。
二叉堆满足二个特性:
1)父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2)每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆
堆分为大顶堆和小顶堆,其中下图(1)中是大顶堆,(2)为小顶堆
2. 堆排序的思想
利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。
其基本思想为(大顶堆):
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
2)将堆顶元素R[1]与最后一个元素R
交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R
;
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)父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2)每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆
堆分为大顶堆和小顶堆,其中下图(1)中是大顶堆,(2)为小顶堆
2. 堆排序的思想
利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。
其基本思想为(大顶堆):
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
2)将堆顶元素R[1]与最后一个元素R
交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R
;
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位于堆顶不满堆的性质,则需调整继续调整
其实就是每次把堆顶元素和最后没交换过的子节点元素交换,然后将此子节点之前的二叉树重新排序,变成大顶堆。
如果按递增排序,需要用到大顶堆,每次把堆顶(无序堆最大值)放到有序堆前面,重新得到无序区大顶堆;
如果按递减排序,需要用到小顶堆,每次把堆顶(无序堆最小值)放到有序堆前面,重新得到无序区小顶堆;
程序如下(包含递增和递减):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace conHeapSort { class HeapSort { private static Boolean Asce = true;//heap sorted by ascending order private static Boolean Desc = false;//heap sorted by descending order static void Main(string[] args) { List<int> input = new List<int>(); HeapSort exap = new HeapSort(); String str; input.Add(0);//start from index one str = Console.ReadLine(); while(str != "exit"){ input.Add(Int32.Parse(str)); str = Console.ReadLine(); } exap.SortHeap(input, Desc); for (int i = 1; i < input.Count; i++ ) { Console.WriteLine(input[i].ToString()); } } void SortHeap(List<int> data, Boolean order) { BuildHeap(data, order); if (order) { for (int i = data.Count - 1; i >= 1; i--) { Swap(data, 1, i); //exchange between index 1 and index i MaxHeap(data, 1, i - 1); //get max heap } } else { for (int i = data.Count - 1; i >= 1; i--) { Swap(data, 1, i);//exchange between index 1 and index i MinHeap(data, 1, i - 1); //get min heap } } } void BuildHeap(List<int> data, Boolean order) { if (order) //make maximal heap { for (int i = data.Count / 2; i >= 1; i--) { MaxHeap(data, i, data.Count - 1); //initialize } } else //make minimal heap { for (int i = data.Count / 2; i >= 1; i--) { MinHeap(data, i, data.Count - 1);//initialize } } } //get max heap void MaxHeap(List<int> data, int i, int size) { int lchild = 2 * i; int rchild = lchild + 1; int max = i; if (i <= size / 2) { if (lchild <= size && data[lchild] > data[max]) { max = lchild; } if (rchild <= size && data[rchild] > data[max]) { max = rchild; } if (max != i) { Swap(data, i, max); //exchange child and parent node MaxHeap(data, max, size); //continue to adjust } } } //get min heap void MinHeap(List<int> data, int i, int size) { int lchild = 2 * i; int rchild = lchild + 1; int min = i; if (i <= size / 2) { if (lchild <= size && data[lchild] < data[min]) { min = lchild; } if (rchild <= size && data[rchild] < data[min]) { min = rchild; } if (min != i) { Swap(data, i, min);//exchange child and parent node MinHeap(data, min, size); } } } //exchange index1 and index2 in data void Swap(List<int> data, int index1, int index2) { int temp = data[index2]; data[index2] = data[index1]; data[index1] = temp; } } }
相关文章推荐
- 八大排序算法之四选择排序—堆排序(Heap Sort)
- [Java--常见排序算法]--堆排序 (Heap Sort)
- 堆排序(Heap Sort)算法学习
- Insertion or Heap Sort PAT甲级真题(堆排序)
- 堆排序(Heap Sort)算法学习
- 选择排序(2)——堆排序(heap sort)
- 堆排序 heapSort
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 选择排序之堆排序(HeapSort)
- 排序算法之堆排序 Heap Sort
- 排序算法之堆排序(Heap Sort)
- Atitit 算法之道 attilax著 1. 第二部分(Part II) 排序与顺序统计(Sorting and Order Statistics) 1 2. 第六章 堆排序(Heapsort)
- 堆排序 (Heapsort)
- 经典算法(9)- 堆排序(Heapsort)
- 堆排序(heap sort)
- 堆排序(Heap Sort)原理及Java实现
- 堆排序(Heapsort)
- HeapSort -- 堆排序
- 第六章 堆排序(heapsort)
- 堆排序 HeapSort