- 二叉堆是一种完全的二叉树。它分为两种,大顶堆和小顶堆。小顶堆就是左右节点的值都比根节点大。大顶堆就是左右节点的值都比根节点小。二叉堆是用数组表示最方便的一种二叉树。别的二叉树都是用带有左右指针的数据结构表示的。二叉堆用左右指针表示反而有点使用不方便。我们通过数组的标识符,利用完全二叉树的性质,可以很容易的获得一个节点的左右节点和父亲节点。
- 已知节点的位置为num,那么父亲节点为(num-1)/2。左节点为2num+1,右节点为2num+2。涉及的主要算法为两个(1)建立二叉堆(数量为num,小顶堆为例)。从i(1-n(不包含n))开始。每次都intarr[i]和intarr[parent(i)](parent(i)不为0)比较。intarr[i]<intarr[parent(i)],则交换两个位置的值,然后i=parent(i)(parent(i)不为0),1-n-1挨次遍历完毕,完成二叉堆的建立。
- (2)插入数据num,首先比较intarr[0]和num,num大,则交换num和intarr[0]的值。
- 对二叉树进行调整。t=0.挨个比较左右节点的值是否比intarr[t]小,小的话,优先交换右节点。交换完成后,t=rightchild(t)(t<n),然后在进行比较即可,直到调整整个二叉堆。
- 整体的实现代码如下:
- #include
#include
#include
#define NUM 50
using namespace std;
int intarr[NUM];
int parent(int n)
{
return (n - 1) / 2;
}
int leftChild(int n)
{
return 2 * n + 1;
}
int rightChild(int n)
{
return 2 * n + 2;
}
void buildHeap(int n)
{
for (int i = 1; i < n; i++)
{
int ti = i;
while (ti !=0 && intarr[parent(ti)] > intarr[ti])
{
int temp = intarr[parent(ti)];
intarr[parent(ti)] = intarr[ti];
intarr[ti] = temp;
ti = parent(ti);
}
}
}
void insertNumber(int n, int i)
{
if (intarr[i] < intarr[0])
{
return;
}
else
{
int temp = intarr[0];
intarr[0] = intarr[i];
intarr[i] = temp;
int ti = 0;
while ((leftChild(ti) < n && intarr[leftChild(ti)] < intarr[ti]) ||
(rightChild(ti) < n && intarr[rightChild(ti)] < intarr[ti]))
{
if (rightChild(ti) < n && intarr[rightChild(ti)] < intarr[ti])
{
int temp = intarr[rightChild(ti)];
intarr[rightChild(ti)] = intarr[ti];
intarr[ti] = temp;
ti = rightChild(ti);
}
else
{
int temp = intarr[leftChild(ti)];
intarr[leftChild(ti)] = intarr[ti];
intarr[ti] = temp;
ti = leftChild(ti);
}
}
}
}
int main()
{
srand((unsigned)time(NULL));
for (int i = 0; i < NUM; i++)
{
int val = rand() % 100;
intarr[i] = val;
cout << val << " ";
if ((i + 1) % 10 == 0)
{
cout << endl;
}
}
cout << endl;
int n = 10;
buildHeap(n);
for (int i = 10; i < NUM; i++)
{
insertNumber(n, i);
}
for (int i = 0; i < n; i++)
{
cout << intarr[i] << " ";
}
cout << endl;
system(“pause”);
return 0;
}
输出结果:
复杂度分析,如果我们找一个M数组的前N个大的数据。采用循环操作,复杂度为MN。而二叉堆的复杂度为MlogN。
const_cast可以把一些const的属性的变量为我所用并做一些修改再使用(当然原变量是不修改的),const_cast只允许转换为指针或者引用的变量哦(只有这两个可以转换)。
#include
using namespace std;
int main()
{
const int a = 10;
int *p = const_cast<int *>(&a);
*p = *p + 20;
cout << p << endl;
cout << a << endl;
system(“pause”);
return 0;
}
执行结果
30
10
说明const_cast是不修改原变量的值得。
引用的使用:
#include
using namespace std;
int main()
{
const int a = 10;
int &p = const_cast<int &>(a);
p = p + 20;
cout << p << endl;
cout << a << endl;
system(“pause”);
return 0;
}
执行结果:
30
10
当const的变量为map类型的时候,需要特殊的操作技巧:
#include
#include(const_cast<mapInt *>(&maptest)))[1];
//auto num = (const_cast<mapInt &>(maptest))[1];
cout<<num<<endl;
system(“pause”);
return 0;
}
执行结果:
5
很神奇
神奇的二叉堆和const_static的使用
最新推荐文章于 2023-07-14 01:52:05 发布