堆排序(含算法分析和代码实现)

/*
基本思想
{
    选择排序:每一趟在后面n-i+1个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到n-i趟做完,待排序元素只剩下1个,就不用再选了。(堆排序为例)
    堆排序步骤(大根堆为例):
    {
		基本思想:首先将表中的n个元素建成初始堆,根据堆本身的特点可知,栈顶元素就是最大值。输出栈顶元素后,通常将堆底元素送入栈顶,但这时候根节点可能不满足堆的性质
        堆被破坏,将栈顶元素向下调整使得其继续保持大顶堆的性质,在输出栈顶元素,如此重复,直到堆中仅剩一个元素为止。
        可见堆排序需要解决俩个问题:
        1.如何将无序序列构造成初始堆
        2.输出栈顶元素后,如何将剩余元素调整成新的堆
    }
    堆排序算法分析:
    {
        空间效率:使用了常数个辅助单元,空间复杂度为O(1)
        时间复杂度为O(nlog2(n))
        稳定性:不稳定

    }
}
*/
#include<stdio.h>
#include<stdlib.h>
#define size 9
typedef struct 
{
    int data[size];
    int length;
}sqlist;
//初始化顺序表
void inist(sqlist &s)
{
    int yuan[size-1]={57,45,78,41,12,60,53,19};
    s.data[0]=0; //作为暂存单元 
	s.length=size-1;
    for(int i=1;i<=s.length;i++)
    s.data[i]=yuan[i-1]; 
}
//输出顺序表
void pirintlist(sqlist s)
{
    int i;
    for(i=1;i<=s.length;i++)
    {
        printf("%d ",s.data[i]);
    }
}
//建立大根堆
void headajust(sqlist &s,int k,int len)
{
    s.data[0]=s.data[k];
    for(int i=2*k;i<=len;i*=2)
    {
        if(i<len&&s.data[i]<s.data[i+1])		//这里比较孩子结点最大的一个
        i++;
        if(s.data[0]>=s.data[i])		//如果孩子结点小于双亲结点,无需要交换
        break;
        else
        {							//否则,将双亲结点的值替换掉成最大的孩子结点,并记录他的位置
            s.data[k]=s.data[i];
            k=i;
        }
    }
    s.data[k]=s.data[0];	//将交换最大孩子结点的位置上,放入交换的双亲结点
}
void buildmaxheap(sqlist &s,int len)
{
    for(int i=len/2;i>0;i--)    // 从【n/2】~1 反复调整堆
	{
		headajust(s,i,len);
	}
}
//堆排序算法
void heapsort(sqlist &s,int len)
{
    int temp,i,f=1;
    buildmaxheap(s,len);
    for(i=len;i>1;i--)			
    {
        temp=s.data[i];			//每次将最大的元素(下标为1)与数组下表i的元素交换,使得最大,次大元素放到数组最后
        s.data[i]=s.data[1];
        s.data[1]=temp;
        headajust(s,1,i-1);		//交换后,从1~i的表中重新建立堆
		printf("\n第%d趟排序表内容为:\n",f++);
		pirintlist(s);
    }
}
int main()
{
    sqlist s;
    inist(s);
	printf("无序序列表内容为:\n");
    pirintlist(s);
    heapsort(s,s.length);
	printf("\n排序后列表内容为:\n");
    pirintlist(s);
    
	return 0;
}

代码运行图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值