zoukankan      html  css  js  c++  java
  • 堆排序

    原创


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

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

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

  • 相关阅读:
    关于进程exit后,内存释放释放的实践
    《C语言基础日常笔记》
    阿里巴巴重磅推出,让你的电脑变成云服务器,只要 5 分钟! 5 分钟! 5 分钟!
    vs2010下使用绘图控件MsChart的方法
    归纳整理Linux下C语言常用的库函数----文件操作
    归纳整理Linux下C语言常用的库函数----字符串转换、字符测试、及内存控制
    参考 generate-parentheses
    初步整理数仓知识 2017
    论文学习 数码相机系统
    论文学习:数码相机处理器的结构设计
  • 原文地址:https://www.cnblogs.com/chiweiming/p/9629883.html
Copyright © 2011-2022 走看看