1.堆:
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<=K2i+2 ,则称为小堆(或大堆)。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
性质:
1. 堆中某个节点的值总是不大于或不小于其父节点的值;
2. 堆总是一棵完全二叉树。
2.堆排序和创建初始堆
#include<iostream>
using namespace std;
void HeapAdjust(int r[], int s, int t) {
//先将现在要调整的根节点的数据和下标记录下来
int temp = r[s];
int i = s;
for (int j = 2 * i; j <= t; j = 2 * j) {
//2*i和2*i+1是下标为i的结点的孩子结点的下标,找出其中最大的
if (j < t && r[j] < r[j + 1]) {
j = j + 1;
}
//如果孩子结点中最大的值都没有根节点的值大,那么就不用交换了
//注意这里一直用的是temp,temp的值在for循环中不会改变
if (temp > r[j]) {
break;
}
r[i] = r[j];//交换
i = j;
}
r[i] = temp;
}
void HeapSort(int r[], int n) {
//创建初始堆,从n/2开始是因为第n/2个结点才开始拥有孩子结点
for (int i = n / 2; i > 0; i--) {
HeapAdjust(r, i, n);
}
for (int i = n; i > 1; i--) {
r[0] = r[1];
r[1] = r[i];
r[i] = r[0];
HeapAdjust(r, 1, i - 1);
}
}
int main()
{
//对1--n范围的数据进行排序,s[0]是作为进行交换数据的位置
int s[20] = { 0,2,5,4,1,9,6,7,10,15 };
HeapSort(s, 9);
for (int i = 1; i <= 9; i++) {
cout << s[i] << " ";
}
return 0;
}
这是我自己改的HeapAdjust函数:
void HeapAdjust(int r[], int s, int t) {
//先将现在要调整的根节点的数据和下标记录下来
int temp = r[s];
int i = s;
for (int j = 2 * i; j <= t; j = 2 * j) {
//2*i和2*i+1是下标为i的结点的孩子结点的下标,找出其中最大的
if (j < t && r[j] < r[j + 1]) {
j = j + 1;
}
//如果孩子结点中最大的值都没有根节点的值大,那么就不用交换了
if (temp > r[j]) {
break;
}
//交换
r[i] = r[j];
r[j] = temp;
temp = r[i];
i = j;
}
}
3.优先队列(priority_queue)
优先队列(priority_queue)的原理及用法
一、优先队列的原理及使用
std::priority_queue:在优先队列中,优先级高的元素先出队列,并非按照先进先出的要求,类似一个堆(heap)。其模板声明带有三个参数,priority_queue<Type, Container, Functional>, 其中Type为数据类型,Container为保存数据的容器,Functional为元素比较方式。Container必须是用数组实现的容器,比如 vector, deque. STL里面默认用的是vector. 比较方式默认用operator< , 所以如果把后面两个参数缺省的话,优先队列就是大顶堆,队头元素最大。
priority_queue(),默认按照从小到大排列。所以top()返回的是最大值而不是最小值!
使用greater<>后,数据从大到小排列,top()返回的就是最小值而不是最大值!
如果使用了第三个参数,那第二个参数不能省,用作保存数据的容器!!!!
priority_queue<int, greater<>> pq;//这是错误的
priority_queue<int,vector<int> , greater<>> pq;//这是对的
这里再提一嘴,greater<int>与greater<int>() 的区别,这要根据函数原型要求参数是函数对象类型还是要求参数是结构类型。greater<int> 对应于结构的类型,greater< int>()对应于没有参数且返回类型更大的函数的类型。比如multimap中使用不带括号的,sort使用带括号的。
二、基本操作
优先队列在头文件#include <queue>中;
其声明格式为:priority_queue <int> ans;//声明一个名为ans的整形的优先队列
基本操作有:
empty( ) //判断一个队列是否为空
pop( ) //删除队顶元素
push( ) //加入一个元素
size( ) //返回优先队列中拥有的元素个数
top( ) //返回优先队列的队顶元素
优先队列的时间复杂度为O(logn),n为队列中元素的个数,其存取都需要时间。
三、使用方法
#include<iostream>
#include<queue>
using namespace std;
int main()
{
vector<int> aa = { 1,2,4,3,8,6,1,4 };
priority_queue<int, vector<int>,greater<>> pq;
for (int i = 0; i < aa.size(); i++) {
pq.push(aa[i]);
}
sort(aa.begin(), aa.end());
for (int i = 0; i < aa.size(); i++)
cout << aa[i];
cout << endl;
for (int i = 0; i < aa.size(); i++) {
cout << pq.top();
pq.pop();
}
//cout << pq << endl;
system("pause");
return 0;
}