堆的创建与应用以及堆排序
2018-01-22 19:24
225 查看
1.堆的概念:
如果有一个关键码的集合K={k0,k1,k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki<=k2*i+1且ki<=k2*+2(ki>=k2*i+1且ki>=k2*i+2)。(i=0,1,2,…)则称这个堆为最小堆(或最大堆)
堆的特性:
用来存数据——>完全二叉树形式
任意结点满足:1.leftchild=2*i+1;
2.rightchild=2*i+2;
最小堆:任一结点的关键码均小于等于它的左右孩子的关键码,位于堆顶结点的关键码最小。下图为最小堆。
最大堆:任一结点的关键码均大于等于它的左右孩子的关键码,位于堆顶结点的关键码最大。下图为最大堆。
堆的创建:
先将数组中的元素存贮起来,如下图所示。
显然其并不是最小堆或最大堆的形式,所以要进行调整。
(现调整为最小堆)
从其倒数第一个非叶子的位置开始调整,第一次:i=(8-2)/2。检测以i为根节点的子树是否满足最小堆,若满足则不进行调整,若不满足开始调整。
具体的堆的创建部分代码为:
堆的插入:
堆的插入每次都是在已经建好的最小堆的后面插入,插入之后,有可能破坏堆的结构,需对堆进行调整。
调整的方法为从下向上调整,因为上面的元素已经是按照最小堆的形式列出,所以需用向上调整的方法。
具体方法为:
比较parent与child的值域,若parent值域大于child值域,则进行交换,之后再向上调整。
具体的代码为:
堆的删除:堆的删除是针对于堆顶元素,删除堆顶元素。
具体分为三种情况:
1.堆为空:则直接返回
2.堆中只有一个元素—->直接删除之后返回
3.堆中有多个元素:先将最后一个元素与堆顶元素进行交换,之后删除堆顶元素,再进行向下调整。
完整的代码为:
2.给堆添加比较器,用户可以任意控制大堆或者小堆
3.用堆封装优先级队列
优先级队列:priority_queue,其为0个或多个元素的集合。
4.堆排序:其为选择排序的一种,
具体步骤为:<1>创建堆
<2>调整。排序
升序:若升序时建小堆的话,下标最小的元素最小,但是每次选出最小的之后剩下的都要重新再调整为一个小堆。
若建大堆的话,根节点是最大的值,每次只要和其孩子进行交换,再进行调整。
以此结论:
升序—–>建大堆
降序——>建小堆
如果有一个关键码的集合K={k0,k1,k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki<=k2*i+1且ki<=k2*+2(ki>=k2*i+1且ki>=k2*i+2)。(i=0,1,2,…)则称这个堆为最小堆(或最大堆)
堆的特性:
用来存数据——>完全二叉树形式
任意结点满足:1.leftchild=2*i+1;
2.rightchild=2*i+2;
最小堆:任一结点的关键码均小于等于它的左右孩子的关键码,位于堆顶结点的关键码最小。下图为最小堆。
最大堆:任一结点的关键码均大于等于它的左右孩子的关键码,位于堆顶结点的关键码最大。下图为最大堆。
堆的创建:
先将数组中的元素存贮起来,如下图所示。
显然其并不是最小堆或最大堆的形式,所以要进行调整。
(现调整为最小堆)
从其倒数第一个非叶子的位置开始调整,第一次:i=(8-2)/2。检测以i为根节点的子树是否满足最小堆,若满足则不进行调整,若不满足开始调整。
具体的堆的创建部分代码为:
Heap(const T*array,size_t size)//堆的创建 { //1.将数组中的元素存起来 _array.resize(size); for (size_t i = 0; i < size; i++) { _array[i] = array[i]; } //2.向下调整 int root = (size - 2) >> 1; for (; root >= 0; root--) { _AdjustDown(root); } } void _AdjustDown(size_t parent)//向下调整 { size_t child = parent * 2 + 1; size_t size = _array.size(); while (child < size) { if ((child + 1 < size) && (_array[child] > _array[child + 1])) { child += 1; } if (_array[parent]>_array[child]) { swap(_array[parent], _array[child]); parent = child; child = parent * 2 + 1;//继续走到其左侧,进行调整 } else { break; } } }
堆的插入:
堆的插入每次都是在已经建好的最小堆的后面插入,插入之后,有可能破坏堆的结构,需对堆进行调整。
调整的方法为从下向上调整,因为上面的元素已经是按照最小堆的形式列出,所以需用向上调整的方法。
具体方法为:
比较parent与child的值域,若parent值域大于child值域,则进行交换,之后再向上调整。
具体的代码为:
void Push(const T& data) { _array.push_back(data); if (_array.size() > 1) { _AdjustUp(_array.size() - 1); } } void _AdjustUp(size_t child)//向上调整 { size_t size = _array.size(); size_t parent = (size - 2) >> 1; while (child > 0) { if (_array[parent] > _array[child]) { swap(_array[parent], _array[child]); child = parent; parent = (child - 1) >> 1; } else { break; } } }
堆的删除:堆的删除是针对于堆顶元素,删除堆顶元素。
具体分为三种情况:
1.堆为空:则直接返回
2.堆中只有一个元素—->直接删除之后返回
3.堆中有多个元素:先将最后一个元素与堆顶元素进行交换,之后删除堆顶元素,再进行向下调整。
void Pop() { if (Size()==0) return; else { size_t last = _array.size() - 1; swap(_array[0], _array[last]); _array.pop_back(); //2.向下调整 _AdjustDown(0); } }
完整的代码为:
#include<iostream>
#include<vector>
using namespace std;
template<class T>
class Heap
{
public:
Heap()
{}
Heap(const T*array,size_t size)//堆的创建
{
//1.将数组中的元素存起来
_array.resize(size);
for (size_t i = 0; i < size; i++)
{
_array[i] = arra
4000
y[i];
}
//2.向下调整
int root = (size - 2) >> 1;
for (; root >= 0; root--)
{
_AdjustDown(root);
}
}
void Push(const T& data)
{
_array.push_back(data);
if (_array.size() > 1)
{
_AdjustUp(_array.size() - 1);
}
}
void Pop() { if (Size()==0) return; else { size_t last = _array.size() - 1; swap(_array[0], _array[last]); _array.pop_back(); //2.向下调整 _AdjustDown(0); } }
T Top()const
{
return _array[0];
}
bool Empty()const
{
return _array.empty();
}
size_t Size()const
{
return _array.size();
}
private:
void _AdjustDown(size_t parent)//向下调整
{
size_t child = parent * 2 + 1;
size_t size = _array.size();
while (child < size)
{
if ((child + 1 < size) && (_array[child] > _array[child + 1]))
{
child += 1;
}
if (_array[parent]>_array[child])
{
swap(_array[parent], _array[child]);
parent = child;
child = parent * 2 + 1;//继续走到其左侧,进行调整
}
else
{
break;
}
}
}
void _AdjustUp(size_t child)//向上调整
{
size_t size = _array.size();
size_t parent = (size - 2) >> 1;
while (child > 0)
{
if (_array[parent] > _array[child])
{
swap(_array[parent], _array[child]);
child = parent;
parent = (child - 1) >> 1;
}
else
{
break;
}
}
}
private:
vector<T>_array;
};
int main()
{
int array[] = { 53, 17, 78, 9, 45, 65, 87, 23 };
Heap<int>h(array, sizeof(array) / sizeof(int));
h.Push(10);
cout << boolalpha << h.Empty() << endl;
cout << h.Top() << endl;
cout << h.Size() << endl;
h.Pop();
cout << h.Size() << endl;
cout << h.Empty() << endl;
system("pause");
return 0;
}
2.给堆添加比较器,用户可以任意控制大堆或者小堆
#include<iostream> #include<vector> using namespace std; template<class T> struct Greater { bool operator()(const T&a, const T&b) { return a > b; } }; template<class T> struct Smaller { bool operator()(const T&a, const T&b) { return a < b; } }; template<class T, class compare=Smaller<T>> class Heap { public: Heap() {} Heap(T*array, int size)//堆的创建 { //1.将数组中的元素存起来 _array.resize(size); for (int i = 0; i < size; i++) { _array[i] = array[i]; } //2.向下调整 int root = (size - 2) >> 1; for (; root >= 0; root--) { _AdjustDown(root); } } void Push(const T& data) { _array.push_back(data); if (_array.size() > 1) { _AdjustUp(_array.size() - 1); } } void Pop() { if (Size()==0) return; else { int last = _array.size() - 1; swap(_array[0], _array[last]); _array.pop_back(); //2.向下调整 _AdjustDown(0); } } T Top()const { return _array[0]; } bool Empty()const { return _array.empty(); } size_t Size()const { return _array.size(); } private: void _AdjustDown(int parent)//向下调整 { int child = parent * 2 + 1; int size = _array.size(); while (child < size) { if ((child + 1 < size) && (compare()(_array[child], _array[child + 1]))) { child += 1; } if (compare()(_array[parent], _array[child])) { swap(_array[parent], _array[child]); parent = child; child = parent * 2 + 1;//继续走到其左侧,进行调整 } else return; } } void _AdjustUp(int child)//向上调整 { int size = _array.size(); int parent = (size - 2) >> 1; while (child > 0) { if (compare()(_array[parent], _array[child])) { swap(_array[parent], _array[child]); child = parent; parent = (child - 1) >> 1; } else { break; } } } private: vector<T>_array; }; int main() { int array[] = { 53, 17, 78, 9, 45, 65, 87, 23 }; Heap<int,Smaller<int>>h(array, sizeof(array) / sizeof(int)); //Heap<int, Greater<int>>h1(array, sizeof(array) / sizeof(array[0])); h.Push(10); cout << boolalpha << h.Empty() << endl; cout << h.Top() << endl; cout << h.Size() << endl; h.Pop(); cout << h.Size() << endl; cout << h.Empty() << endl; system("pause"); return 0; }
3.用堆封装优先级队列
优先级队列:priority_queue,其为0个或多个元素的集合。
#include<iostream> #include<vector> #include"Heap.h" using namespace std; template<class T,class compare> class priority { public: priority() {} void push(const T&data) { h.Push(data); } void pop() { h.Pop(); } T Top() { return h.Top(); } size_t Size() { return h.Size(); } bool Empty() { return h.Empty(); } private: Heap<T, compare>h; }; int main() { /*int array[] = { 53, 17, 78, 9, 45, 65, 87, 23 }; Heap<int,Smaller<int>>h(array, sizeof(array) / sizeof(int));*/ //Heap<int, Greater<int>>h1(array, sizeof(array) / sizeof(array[0])); priority<int, Greater<int>>p; p.push(10); p.push(25); cout << boolalpha << p.Empty() << endl; cout << p.Top() << endl; cout << p.Size() << endl; p.pop(); cout << p.Size() << endl; cout << p.Empty() << endl; system("pause"); return 0; }
4.堆排序:其为选择排序的一种,
具体步骤为:<1>创建堆
<2>调整。排序
升序:若升序时建小堆的话,下标最小的元素最小,但是每次选出最小的之后剩下的都要重新再调整为一个小堆。
若建大堆的话,根节点是最大的值,每次只要和其孩子进行交换,再进行调整。
以此结论:
升序—–>建大堆
降序——>建小堆
#include<iostream> #include<vector> using namespace std; void AdjustDown(int* array, size_t size, size_t parent) { size_t child = parent * 2 + 1; while ( b70d child < size) { if (child + 1 < size&&array[child + 1] > array[child]) { ++child; } if (array[child]>array[parent]) { std::swap(array[child], array[parent]); parent = child; child = parent * 2 + 1; } else { break; } } } void HeapSort(int* array, size_t size) { //见堆 for (int i = (size - 2) / 2; i >= 0; --i) { AdjustDown(array, size, i); } for (size_t i = 0; i < size; ++i) { std::swap(array[0], array[size - i - 1]);//最后一个数的下标 AdjustDown(array, size - i - 1, 0);//个数 } } int main() { int array[] = { 10, 11, 12, 14, 12, 1, 2, 3, 4, 15, 19 }; int len = sizeof(array) / sizeof(array[0]); HeapSort(array, len); for (size_t i = 0; i < len; ++i) { cout << array[i] << " "; } system("pause"); return 0; }
相关文章推荐
- 百度地图SDK下载以及创建应用(申请Key)和本地导入Demo
- qt动态库与静态库编译、应用以及pri文件创建
- OC_关于Object-C类的创建以及应用
- 以太坊创建多重签名钱包以及应用
- Android_AsyncTask详解及其应用(三)_图片错位以及AsyncTask重复创建的问题
- Bada学习- C++以及Flash应用开发流程之创建应用工程
- 堆排序,以及stl中的堆应用
- 如何创建一个新浪微博应用以及获得Access token
- Bada学习-(三十三) C++以及Flash应用开发流程之创建应用工程
- Sqlite创建database的两种方法,以及源码分析,以及抽象类如何在SqliteHelper中应用
- Android_AsyncTask详解及其应用(三)_图片错位以及AsyncTask重复创建的问题
- Woocomerce接入支付宝支付功能(一)——创建应用以及请求支付
- 傻瓜式IOS发布教程(一)iTunes Connect创建应用以及内购
- 使用概要管理工具创建定制概要文件,并在此节点上 创建集群以及在集群服务器中部署应用
- 二叉树的创建、前序中序后序递归遍历与非递归遍历、层序遍历以及二叉树简单应用的C语言实现
- django创建一个新项目以及创建一个新的应用
- 应用dispatch_once创建单例以及其他2中方式
- 傻瓜式IOS发布教程(一)iTunes Connect创建应用以及内购
- 创建JDBC模板简化代码、JDBC应用的事务管理以及连接池的作用
- 傻瓜式IOS发布教程(一)iTunes Connect创建应用以及内购