STL篇 ---排序算法---------heap函数

前言:

我们先来学习一下不用STL算法里的Heap函数,自己如何去实现一个堆?要明白,堆其实就是二叉树排序,跟树是有关系的。

知识点:

1、堆是一颗完全二叉树;

2、堆中的某个结点的值总是大于等于(最大堆)或小于等于(最小堆)其孩子结点的值。

3、堆中每个结点的子树都是堆树。

如下图(是个小根堆)

在这里插入图片描述

大根堆
在这里插入图片描述

构造代码:

第一步:先把堆构造出来`

//第一种方法就是边读入边构造
//建立小根堆
void siwfup(int i,int k){
	whiel(i){
		if(a[i]<a[i/2]){
			swap(a[i],a[i/2]);
		}
		else break;
		i = i/2;
	}
void inio(){
	int t;
	cin>>t;
	for(int i=0;i<t;++i){
		int k;
		cin>>k;
		siwfup(i,k);
	}
	reutrn 0;
}

//第二种比较简单,直接存入数组,读取完后才调整

void swifdown(int i){
	int k;  //k变量用来存小值
	while(i*2>t){  //首先判断是否有左边的儿子
		if(a[i]>a[i*2]) k = i*2;
		else k = i;
		if(i*2+1>t && a[i*2+1]<a[k]) k = i*2+1;  //再判断右边儿子
		if(k==i) break;
		else{
			swap(a[i],a[k]);
			i = k;
		}
	}
}
void inio(){
	int t;  cin>>t;
	for(int i=0;i<t;++i){
		cin>>a[i];
	}
	
	for(int i=t/2;i>=0;--i){
		swifdown(i);
	}
	return ;
}

第二步:输出待排序的数值,也就是删除节点,输出节点的操作,其实也就是把头和尾相互调换,然后重新调整为小根堆;

void print(int t){
	int n = t;
	for(int i=0;i<n;++i){
		cout<<a[0]<<' ';
		swap(a[0],a[t]);
		--t;
		swifdown(0);
	}
}
额外一步:(有时还可能继续添加元素)
void add(int i,int x){   //i是下标,x是元素
	siwfup(i,x);
	return ;
}

——————————————————————————

                  分割线
STL库:
  1. make_heap();
  2. push_heap();
  3. pop_heap();
  4. sort_heap();

make_heap

STL中的通过make_heap创建的堆,默认是大顶堆(max heap),即每个非叶子节点元素的值均不”小于”(默认使用<作为比较准则)其左右孩子节点。要改变堆的建立准则,可以自己制定一个比较函数.

// 1
template< class RandomIt >
void make_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void make_heap( RandomIt first, RandomIt last, Compare comp );

示例代码:

(默认的大根堆,make_heap需使用随机迭代器来创建)

vector<int> vi{8, 3, 4, 7, 5, 6};
make_heap(vi.begin(), vi.end());
for(auto i:vi){
	cout<<i<<' ';
}        // vi:  8 7 6 3 5 4

~
(自己写比较函数)

bool cmp(int a,int b){
	return a<b;
}
vector<int> vi{8, 3, 4, 7, 5, 6};
make_heap(vi.begin(), vi.end(),cmp);
for(auto i:vi){
	cout<<i<<' ';
}        // vi:  3 5 4 7 8 6

push_heap

// 1
template< class RandomIt >
void push_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void push_heap( RandomIt first, RandomIt last, Compare comp );

调用push_heap之前必须调用make_heap创建一个堆
首先数组push_back插入元素,然后再调用push_heap,它会使最后一个元素插到合适位置
注意,push_heap中的_Compare和make_heap中的_Compare参数必须是一致的,不然会插入堆失败,最后一个元素还是在最后位置,导致插入失败

vector<int> vi{8, 3, 4, 7, 5, 6};
make_heap(vi.begin(), vi.end());

vi.push_back(9);
push_heap(vi.begin(), vi.end());

for(auto i:vi){
	cout<<i<<' ';
}        // vi:  9 8 7 6 3 5 4

~

pop_heap

它会将堆顶元素(数组第一个位置)和数组最后一个位置对调,然后你可以调用数组pop_back,删除这个元素
注意,pop_heap中的_Compare和make_heap中的_Compare参数必须是一致的,不然会失败

// 1    
template< class RandomIt >
void pop_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void pop_heap( RandomIt first, RandomIt last, Compare comp );

示例
vector<int> v1{6, 1, 2, 5, 3, 4};
make_heap(v1.begin(), v1.end());   //6 5 4 1 3 2

pop_heap(v1.begin(), v1.end());   //5 3 4 1 2 6
v1.pop_back();

for(auto i:v1) cout<<i<<' ';  // 5 3 4 1 2 

~

sort_heap

sort_heap就是经典的堆排序算法,通过每次弹出堆顶直到堆为空,依次被弹出的元素就组成了有序的序列了。也可以想到应该是多次调用pop_heap()进行调整的。

// 1
template< class RandomIt >
void sort_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void sort_heap( RandomIt first, RandomIt last, Compare comp );

~

示例

vector<int> vi{8, 3, 4, 7, 5, 6};
make_heap(vi.begin(), vi.end());
sort_heap(vi.begin(),vi.end());
for(auto i:vi){
	cout<<i<<' ';
}        // vi:  3 4 5 6 7 8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值