• 堆排序


    原创


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

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

    • 一个结点的下标为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

  • 相关阅读:
    vue axios的使用
    html5 css写出一个实心三角形和空心三角行
    弹出新页面并使整个旧页面背景变暗功能的实现代码
    radio 单选按钮 选中多个
    搭建脚手架cli2.x环境
    页面滚动条位置触发事件
    DataGridView行号发生变化 使用的事件
    eclipse git 忽略文件
    eclipse git 分享项目到GitHub上
    eclipse git 创建新分支 合并分支 删除分支
  • 原文地址:https://www.cnblogs.com/chiweiming/p/9629883.html
Copyright © 2020-2023  润新知