堆排序

原创


堆排序和快速排序的时间复杂度是相同的,掌握堆排序也是非常重要的!

用一维数组存储堆,有以下规律:

  • 一个结点的下标为i,其左儿子下标为i*2,右儿子下标为i*2+1;
  • 一棵二叉树的最后一个非叶结点的下标为n/2;

首先讲述堆向下调整的过程:

    假设从根结点开始向下调整堆(调整为最小堆),将结点i与两个子结点中较小的一个交换,

假如i与右儿子交换了,将右儿子的坐标赋值给i,然后再重复上面的比较过程和交换过程,直到根

结点比两个子节点都小,说明调整完毕!

排序过程就是将需要排序的数输入数组后,从最后一个非叶子结点开始向下调整,接着将倒数第二个

非叶子结点向下调整!

 1 import java.util.*;
 2 
 3 public class 堆排序 {
 4     
 5     static int n;    //需排序的个数
 6     static int array[];
 7     
 8     static void swap(int a,int b) {
 9         int temp;
10         temp=array[a];
11         array[a]=array[b];
12         array[b]=temp;
13     }
14     
15     //向下调整
16     static void siftdown(int i) {
17         int flag=0;    //标识是否需要继续向下调整
18         int t=i;    //存储3个结点中值最小的结点编号
19         //判断结点i是否有左儿子
20         while(i*2<=n && flag==0) {
21             if(array[i*2]<array[t]) {
22                 t=i*2;
23             }
24             if(i*2+1<=n) {
25                 if(array[i*2+1]<array[t]) {
26                     t=i*2+1;
27                 }
28             }
29             if(t!=i) {
30                 swap(t,i);
31                 i=t;
32             }
33             else {
34                 flag=1;
35             }
36         }
37     }
38     
39     //建立堆
40     static void create() {
41         //第一个非叶结点的编号为n/2
42         for(int i=n/2;i>=1;i--) {
43             siftdown(i);
44         }
45     }
46     
47     static int deletemax() {
48         int t;
49         t=array[1];
50         array[1]=array[n];
51         n--;
52         siftdown(1);
53         return t;
54     }
55 
56     public static void main(String[] args) {
57         Scanner reader=new Scanner(System.in);
58         n=reader.nextInt();
59         array=new int[n+1];
60         //输入要排序的数
61         for(int i=1;i<=n;i++) {
62             array[i]=reader.nextInt();
63         }
64         create();
65         int num=n;
66         for(int i=1;i<=num;i++) {
67             System.out.print(deletemax()+" ");
68         }
69     }
70 
71 }

利用最大堆来排序也可以,每次输出堆顶元素,然后将堆尾元素array[n]和array[1]交换,再从堆顶元素往下调整,

再输出堆顶元素,再输出堆顶元素……

#include<iostream>
#include<memory.h>
#include<malloc.h>
#include<algorithm>
using namespace std;

int n;
int *array;

//向下调整 
void siftdown(int i){
    int flag=0;
    int t=i;    //存储三个结点中最小值的下标 
    while(i*2<=n && flag==0){
        if(array[i*2]>array[t]){
            t=i*2;
        }
        if(i*2+1<=n){
            if(array[i*2+1]>array[t]){
                t=i*2+1;
            }
        }
        if(i!=t){
            swap(array[i],array[t]);
            i=t;
        }
        else{
            flag=1;
        }
    }
}

void create(){
    for(int i=n/2;i>=1;i--){
        siftdown(i);
    }
}

int deletemax(){
    int t;
    t=array[1];
    array[1]=array[n];
    n--;
    siftdown(1);
    return t;
}

int main(){
    cin>>n;
    array=(int *)malloc(sizeof(int)*(n+1));
    for(int i=1;i<=n;i++){
        cin>>array[i];
    }
    //建立堆 
    create();
    int num=n;
    for(int i=1;i<=num;i++){
        cout<<deletemax()<<" ";
    }
    return 0;
}

08:50:29

2018-09-12

原文地址:https://www.cnblogs.com/chiweiming/p/9629883.html