zoukankan      html  css  js  c++  java
  • 堆排序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 }
  • 相关阅读:
    C语言文件路径中的”/“和““
    C语言对文件的操作函数用法详解2
    C语言对文件的操作函数用法详解1
    error MSB8031
    C#操作文件
    C#串口编程
    使用打印方法时,要先引用命名空间: Using System.Drawing.Pringing
    C# 使用printDocument1.Print打印时不显示 正在打印对话框(里面还有一个讨厌的取消按钮)
    在C#里面获得应用程序的当前路径
    Android中的WebView进行直接加载网页(要注意解决权限问题)
  • 原文地址:https://www.cnblogs.com/ywl925/p/2870474.html
Copyright © 2011-2022 走看看