算法与数据结构学习总结-堆排序

堆:通常是一个可以被看做一棵完全二叉树的数组对象

堆的构建(以大顶堆为例)

一.类的构建:

class Heap{
private:
	int *array;//int型指针,用来开辟数组空间
	int nums;//数组中长度的个数
    //less用来比较大小关系
    bool less(int i,int j){
        .....
    }
    //上浮操作
    void Swim(int k){
        .....
    }    
    //下沉操作
    void Sink(int k,int N){
        .....
    }
public:
    //Heap的构造函数
	Heap(int nums){
		array=new int[nums+1];//开辟空间
		this->nums=nums;//记录数组长度	
	}
    //构建大顶堆
	void Input(){
        //跳过了0号位,从1号位开始存储。
		for(int i=1;i<=this->nums;i++){
			cin>>array[i];
			Swim(i);//边输入边上浮
		}
	}
    //输出数组内容
	void Out(){
		for(int i=1;i<=this->nums;i++){
			cout<<array[i]<<" ";
		}
	}
    //进行堆排序
    void Sort(){
		.....
	}
};

相关关键的操作:

上浮:将大的元素朝顶部移动

示意图

实现代码

//上浮操作实现代码
//k代表在数组中的第几位
void Swim(int k){
        //k不需要到第1位,因为那样会和第0位发生一次比较,可能造成值丢失
		while(k>1&&!less(k,k/2)){
            //k位和它的双亲节点进行比较
            //!less(k,k/2)在array[k]>=array[k/2]是返回true
			swap(array[k],array[k/2]);
			k/=2;
		}
	}

 下沉:将小的元素朝底部移动

示意图

实现代码

//下沉操作
//k代表数组中的第几位,N代表堆的底部,即完全二叉树最后一排从左往右数的最后一个所对应在数组的下标
void Sink(int k,int N){
        //2*k代表k的左儿子
		while(2*k<=N){
			int j=2*k;

            //j<N的作用是过滤掉k无右儿子的情况
            //比较左儿子和右儿子的大小,选出二者中最大的
			if(j<N&&less(j,j+1)) j++;

            //如果下方没有比当前节点小的节点了,就下沉停止,跳出循环
			if(array[k]>array[j]) break;

            //交换两个节点的值
			swap(array[k],array[j]);
			k=j;
		}
	}

 堆排序核心代码

void Sort(){
        //记录堆的底部下标
		int len=nums;
		while(len>1){
            //将最大的元素固定在数组最后一位
			swap(array[1],array[len]);
            //将堆缩小,即排除最大的元素,然后对堆顶进行下沉
			Sink(1,--len);
		}
	}

堆的时间复杂度:最坏最好的时间复杂度是nlogn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值