Data Structures and Algorithms --- HEAPSORT (Heap sort)

Heapsort basic introduction

1, heap sort using heap An Algorithm, heap sort this data structure designed for a selection sort , its worst, preferably, are the average time complexity O (nlogn), it is also unstable Sort.

2, the heap is a complete binary tree with the following properties: the value of each node is equal to or greater than the value of its left and right child nodes, is called a large pile top, note : not required left child node and the right child of values the magnitude relationship values.

3, the value of each node is less than or equal to its left child node value, called a small stack top

4, illustrates a heap big top

5, the top of the stack illustrated small

 

Small top stack: arr [i] <= arr [2 * i + 1] && arr [i] <= arr [2 * i + 2] // i corresponding to the number of nodes, i numbered from 0

6, generally using a large top stack ascending, descending stack with a small top 

 HEAPSORT basic idea is:

  1. Collating sequence to be configured into a large pile top
  2. In this case, the entire top of the stack is the maximum value of the sequence of the root node.
  3. To be exchanged with the last element on the end of this time the maximum value.
  4. The remaining n-1 th element of a stack is reconfigured, it would receive the next smallest value of n elements. So again executed, it will be able to get an ordered sequence of.

Can be seen in the process of building the stack top in a large number of elements is gradually reduced, and finally to obtain an ordered sequence of.

Heap sort illustrating steps

Requirements: to give you an array {4,6,8,5,9}, require the use of heap sort, the array in ascending order.

A step configuration initial heap. Given sequence disorder configured to stack a large top (top stack with large ships ascending, descending a small stack top ).

1) Assume that a given sequence disorder following structure

2). In this case we have from the last point on a non-leaf node (leaf node NATURAL without adjustment, the first non-leaf node arr.length / 2-1 = 5 / 2-1 = 1, i.e. below 6 nodes), from left to right, from the bottom is adjusted.

3)  .找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换。

4)  这时,交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6。

 

此时,我们就将一个无序序列构造成了一个大顶堆。

步骤二 将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。

1)  .将堆顶元素9和末尾元素4进行交换

 

2)  .重新调整结构,使其继续满足堆定义

 

3)  .再将堆顶元素8与末尾元素5进行交换,得到第二大元素8.

 

4)  后续过程,继续进行调整,交换,如此反复进行,最终使得整个序列有序

 

再简单总结下堆排序的基本思路:

1).将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;

2).将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;

3).重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

堆排序代码实现

要求:给你一个数组 {4,6,8,5,9} , 要求使用堆排序法,将数组升序排序.

 1 public class HeapSort {
 2 
 3     public static void main(String[] args) {
 4         //要求将数组进行升序排序
 5         //int arr[] = {4, 6, 8, 5, 9};
 6         // 创建要给80000个的随机的数组
 7         int[] arr = new int[8000000];
 8         for (int i = 0; i < 8000000; i++) {
 9             arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
10         }
11 
12         System.out.println("排序前");
13         Date data1 = new Date();
14         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
15         String date1Str = simpleDateFormat.format(data1);
16         System.out.println("排序前的时间是=" + date1Str);
17         
18         heapSort(arr);
19         
20         Date data2 = new Date();
21         String date2Str = simpleDateFormat.format(data2);
22         System.out.println("排序前的时间是=" + date2Str);
23         //System.out.println("排序后=" + Arrays.toString(arr));
24     }
25 
26     //编写一个堆排序的方法
27     public static void heapSort(int arr[]) {
28         int temp = 0;
29         System.out.println("堆排序!!");
30         
31 //        //分步完成
32 //        adjustHeap(arr, 1, arr.length);
33 //        System.out.println("第一次" + Arrays.toString(arr)); // 4, 9, 8, 5, 6
34 //        
35 //        adjustHeap(arr, 0, arr.length);
36 //        System.out.println("第2次" + Arrays.toString(arr)); // 9,6,8,5,4
37         
38         //完成我们最终代码
39         //将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
40         for(int i = arr.length / 2 -1; i >=0; i--) {
41             adjustHeap(arr, i, arr.length);
42         }
43         
44         /*
45          * 2).将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
46               3).重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
47          */
48         for(int j = arr.length-1;j >0; j--) {
49             //交换
50             temp = arr[j];
51             arr[j] = arr[0];
52             arr[0] = temp;
53             adjustHeap(arr, 0, j); 
54         }
55         
56         //System.out.println("数组=" + Arrays.toString(arr)); 
57         
58     }
59     
60     //将一个数组(二叉树), 调整成一个大顶堆
61     /**
62      * 功能: 完成 将 以 i 对应的非叶子结点的树调整成大顶堆
63      * 举例  int arr[] = {4, 6, 8, 5, 9}; => i = 1 => adjustHeap => 得到 {4, 9, 8, 5, 6}
64      * 如果我们再次调用  adjustHeap 传入的是 i = 0 => 得到 {4, 9, 8, 5, 6} => {9,6,8,5, 4}
65      * @param arr 待调整的数组
66      * @param i 表示非叶子结点在数组中索引
67      * @param lenght 表示对多少个元素继续调整, length 是在逐渐的减少
68      */
69     public  static void adjustHeap(int arr[], int i, int lenght) {
70         
71         int temp = arr[i];//先取出当前元素的值,保存在临时变量
72         //开始调整
73         //说明
74         //1. k = i * 2 + 1 k 是 i结点的左子结点
75         for(int k = i * 2 + 1; k < lenght; k = k * 2 + 1) {
76             if(k+1 < lenght && arr[k] < arr[k+1]) { //说明左子结点的值小于右子结点的值
77                 k++; // k 指向右子结点
78             }
79             if(arr[k] > temp) { //如果子结点大于父结点
80                 arr[i] = arr[k]; //把较大的值赋给当前结点
81                 i = k; //!!! i 指向 k,继续循环比较
82             } else {
83                 break;//!
84             }
85         }
86         //当for 循环结束后,我们已经将以i 为父结点的树的最大值,放在了 最顶(局部)
87         arr[i] = temp;//将temp值放到调整后的位置
88     }
89     
90 }
代码

堆排序的速度非常快,在我的机器上 8百万数据 3 秒左右。O(nlogn)

Guess you like

Origin www.cnblogs.com/justBobo/p/11204375.html