树和堆
先验知识
-
二叉树中有两种特殊的二叉树,叫做满二叉树和完全二叉树;
-
满二叉树指的是二叉树内部结点都有两个儿子;
-
完全二叉树就是叶子结点不完整,从右向左连续缺若干结点,只需要用一个一维数组即可存储完全二叉树;
-
已知父亲编号为k,则左儿子是2k,右儿子是2k+1;倘若儿子的编号是x,则父亲结点的编号是x/2;
-
堆是一种特殊的二叉树,所有父节点都比子节点小或者大。
堆的创建
堆的创建有两种方式
方法一:插入的时候调整树的结构
//整体复杂度为O(NlogN)
//建立堆的函数
for(int i = 1; i <= m; i++)
{
scanf("%d", &h[i]);
siftup(i);
}
n = m;
方法二:先存储再调整
//整体复杂度为O(N)
//建立堆的函数
for(int i = 1; i <= m; i++)
{
scanf("%d", &h[i]);
}
n = m;
creat();
//建树函数
void creat()
{
int i;
for(i = n/2; i >= 1; i--)
{
siftdown(i);
}
}
堆排序
方法一:建立最小堆,pop堆顶
#include<bits/stdc++.h>
using namespace std;
int h[101]={0};
int n=0;
void swap(int x, int y)
{
int t;
t = h[x];
h[x] = h[y];
h[y] = t;
}
//向下调整
void siftdown(int i)
{
int flag = 0;
int t;
while( i*2 <= n && flag == 0)
{
//存储最小值
if(h[i] > h[i*2])
t = i*2;
else
t = i;
if(i*2+1 <= n)
{
if(h[t] > h[i*2+1])
t=i*2+1;
}
if(t!=i)
{
swap(t,i);
i=t;
}
else
flag = 1;
}
}
//向上调整
void siftup(int i)
{
int flag = 0;
if(i == 1)return;
while(i!=1 && flag== 0)
{
if(h[i] < h[i/2])
swap(i,i/2);
else
flag = 1;
i=i/2;
}
}
void creat()
{
int i;
for(i = n/2; i >= 1; i--)
{
siftdown(i);
}
}
int deleteValue()
{
int t;
t = h[1];
h[1] = h[n];
n--;
siftdown(1);
return t;
}
int main()
{
int m;
scanf("%d", &m);
// //整体复杂度为O(NlogN)
// //建立堆的函数
// for(int i = 1; i <= m; i++)
// {
// scanf("%d", &h[i]);
// siftup(i);
// }
// n = m;
//整体复杂度为O(N)
//建立堆的函数
for(int i = 1; i <= m; i++)
{
scanf("%d", &h[i]);
}
n = m;
creat();
// for(int i = 1; i <= m; i++)
// {
// printf("%d ", h[i]);
// }
// printf("\n");
for(int i = 1; i <= m; i++)
printf("%d ", deleteValue());
return 0;
}
方法二:建立最大堆,归位最大值
#include<bits/stdc++.h>
using namespace std;
int h[101]={0};
int n=0;
void swap(int x, int y)
{
int t;
t = h[x];
h[x] = h[y];
h[y] = t;
}
//向下调整
void siftdown(int i)
{
int flag = 0;
int t;
while( i*2 <= n && flag == 0)
{
//存储最大值
if(h[i] < h[i*2])
t = i*2;
else
t = i;
if(i*2+1 <= n)
{
if(h[t] < h[i*2+1])
t=i*2+1;
}
if(t!=i)
{
swap(t,i);
i=t;
}
else
flag = 1;
}
}
void creat()
{
int i;
for(i = n/2; i >= 1; i--)
{
siftdown(i);
}
}
//堆排序
void heaport()
{
while(n > 1)
{
swap(1,n);
n--;
siftdown(1);
}
}
int main()
{
int m;
scanf("%d", &m);
for(int i = 1; i <= m; i++)
{
scanf("%d", &h[i]);
}
n = m;
//建堆
creat();
//堆排序
heaport();
for(int i = 1; i <= m; i++)
printf("%d ", h[i]);
return 0;
}
输出结果
14
99 5 36 7 22 17 46 12 2 19 25 28 1 92
1 2 5 7 12 17 19 22 25 28 36 46 92 99