堆排序

本文章的代码使用jetbrains公司旗下的的Clion编写,操作系统位macOS Ventura(13.2.1). 代码没有在dev-c++测试过(dev-c++可能会有相关的空格问题)

//
// Created by 魏志杰 on 2023/7/25.
//

#include "stdio.h"
#define Max 100
#define before  printf("排序前")
#define after   printf("排序后")
#define newline printf("\n")
#define print   printf("%6d", R[i].key)
#define printA  printf("%6d",A[i])
#define Array int A[]={5,7,2,5,9,6,-42,1,67,2,3};




typedef struct {
    int key;
    int data;
}SqType;


//堆排序,不断调整大根堆

//堆排序是从简单排序算法的基础上改进得到的,也是一趟一趟从无序区中选择最小(最大)的一个元素放在有序区中

//我们先来解释一下什么叫大根堆 在树的那一章介绍过(如果没有学习,可以回去喵一眼)一颗含有n个节点的完全二叉树采用顺序存储结构时,它的所有n个元素值

//正好占用一个一维的数组的连续n个空间 ,反过来,一个含有n个元素的数组完全可以看成一个完全二叉树。

//对于一个元素序列对应的一颗完全二叉树,如果每个结点的关键字都不小于其孩子结点的关键字,称为大根堆。如果每个结点的关键字都不大于其孩子结点的关键字
//,称为小根堆

//堆排序的第一步就是要将一个要排序的元素序列调整为大根堆,即建立初始堆,这是通过筛选算法实现的,我们现在来看一下筛选算法

//筛选算法 是将一颗 满足筛选条件的完全二叉树调整为一个大根堆,一颗完全二叉树满足筛选条件 是指除根结点之外,根结点的左子树和右子树都是大根堆。


//
//大根堆筛选算法的基本思想是,从数组中选择一个节点作为根节点,然后通过与其左右子节点比较,将最大值交换到根节点的位置,再以交换后的子节点作为新的根节点,继续向下调整,直到满足大根堆的性质为止。
//
//大根堆筛选算法的步骤如下:
//
//从数组中选择一个节点作为根节点。
//比较根节点与其左右子节点的值,找出其中的最大值。
//如果根节点的值大于等于其左右子节点的值,说明已经满足大根堆的性质,调整结束。
//否则,将根节点与最大值节点交换位置,然后以交换后的节点为新的根节点,继续向下调整.
//筛选算法如下

void sift(SqType R[],int low ,int high){            //对R[low high] 进行堆筛选
    int i =low,j=2*i;                               //R[j]是R[i]的左孩子
    SqType temp=R[i];
    while (j<=high){
        if (j< high && R[j].key <R[j+1].key)
            j++;                                    //若右孩子较大 ,把j指向右孩子
        if (temp.key<R[j].key){
            R[i]=R[j];                              //将R[j]调整到双亲结点的位置上
            i=j;
            j=2*i;
        } else
            break;                                  //已经是大根堆
    }
    R[i]=temp;                                      //被筛选的结点的值放入最终的位置
}

void Sift(SqType R[],int low,int high){
    int i=low,j=2*i;
    SqType temp=R[i];
    while(j<=high){
        if(j<high&&R[j].key<R[j+1].key)
            j++;
        if(temp.key<R[j].key){
            R[i]=R[j];
            i=j;
            j=2*i;
        }
        else break;
    }
    R[i]=temp;
}



void HeapSort(SqType R[], int n) {
    int i;
    SqType temp;
    for (i = n/2;i>=1; i--)           // 从 n/2  开始建立初始堆
        sift(R, i, n );
    for (i = n ; i>=2; i--) {         // 进行 n-1 次排序,完成堆排序
        temp = R[1];                  // swap R[1] R[i]
        R[1] = R[i];
        R[i] = temp;
        sift(R, 1, i - 1);   //筛选
    }
}


void HeapSort_1(SqType  R[],int n){
    int i;
    SqType temp;
    for(i=n/2;i>=1;i--)
        Sift(R,i,n);
    for(i=n;i>=2;i--){
        temp=R[1];
        R[1]=R[i];
        R[i]=temp;
        Sift(R,1,i-1);
    }
}


int  main() {
    SqType R[Max];
    Array;
    for (int i = 0; i < 10; i++)
        R[i].key = A[i];
    before;
    for (int i = 0; i < 10; i++)
        print;
    newline;
    HeapSort(R, 10);
    after;
    for (int i = 1; i <= 10; i++)    //堆循环注意输出的条件
        print;

    newline;
    HeapSort_1(R, 10);
    after;
    for (int i = 1; i <= 10; i++)    //堆循环注意输出的条件
        print;

}

代码结果如下:

posted @ 2023-07-25 18:25  xiaozhounandu  阅读(9)  评论(0编辑  收藏  举报