#include<stdio.h>
//实现堆的各种操作 加入数据 删除数据 调整堆 获取数据
//为方便编程 数组从1开始 小顶堆
int a[100];
int size = 0;
int c,b;
void swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void addAdjust(int a[],int size)
{
int id = size;
while(id/2!=0&&a[id]<a[id/2])//向上调整直至堆顶
{
swap(&a[id],&a[id/2]);
id = id/2;//id 向上前进
}
}
void deleteAdjust(int a[])
{
a[1] = a[size--];
int id = 1;
int child = id*2;
for(;id*2<size;id = child)//保证其至少有左儿子
{
child = id*2;
if(child+1<=size&&a[child]>a[child+1])//在有右儿子的前提下判断谁最小
{
child +=1;
}
if(a[id]>a[child])//若俩儿子中最小值比父节点值小 交换
{
swap(&a[id],&a[child]);
}
else
{
break;
}
}
//id = child 这一步很巧妙的
}
int main()
{
char s[3];
printf("请输入相关命令和数据:\n-a 添加数据\n-d 删除堆顶 \n-g 获取堆顶元素\n-p 打印堆\n-0 退出\n");
while(1)
{
fflush(stdin);
scanf("%s",s);
if(s[1]=='a')
{
scanf("%d",&a[++size]);
addAdjust(a,size);
//printf("-a\n");
}
else if(s[1]=='d')
{
deleteAdjust(a);
printf("堆顶元素已经删除成功!");
//printf("-d\n");
}
else if(s[1]=='g')
{
printf("目前堆顶元素(即最小元素)为:%d\n",a[1]);
//printf("-g\n");
}
else if(s[1]=='p')
{
int i;
for(i=1;i<=size;i++)
printf("%d ",a[i]);
printf("\n");
//printf("-p\n");
}
else if(s[1]=='0')
{
break;
}
else
{
printf("命令错误\n");
printf("请输入相关命令和数据:\n-a 添加数据\n-d 删除堆顶 \n-g 获取堆顶元素\n-p 打印堆\n-0 退出\n");
}
}
printf("操作完成\n");
return 0;
}
#include<stdio.h>
//实现堆的各种操作 加入数据 删除数据 调整堆 获取数据
//为方便编程 数组从1开始 小顶堆
int a[100];
int size = 0;
int c,b;
void swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void addAdjust(int a[],int size)
{
int id = size;
while(id/2!=0&&a[id]<a[id/2])//向上调整直至堆顶
{
swap(&a[id],&a[id/2]);
id = id/2;//id 向上前进
}
}
int max(int a,int b)
{
return a=a>b?a:b;
}
void heapAdjust(int *a,int i,int size)
{
int lchild = 2*i;
int rchild = 2*i+1;
int max = i;
if(lchild<=size&&a[max]>a[lchild])
{
max = lchild;
}
if(rchild<=size&&a[max]>a[rchild])
{
max = rchild;
}
if(max!=i)
{
swap(&a[max],&a[i]);
heapAdjust(a,max,size);
}
else
return;
}
void deleteAdjust(int a[])
{
a[1] = a[size--];
int id = 1;
int child = id*2;
for(;id*2<size;id = child)//保证其至少有左儿子
{
child = id*2;
if(child+1<=size&&a[child]>a[child+1])//在有右儿子的前提下判断谁最小
{
child +=1;
}
if(a[id]>a[child])//若俩儿子中最小值比父节点值小 交换
{
swap(&a[id],&a[child]);
}
else
{
break;
}
}
//id = child 这一步很巧妙的
}
int main()
{
char s[3];
printf("请输入相关命令和数据:\n-a 添加数据\n-d 删除堆顶 \n-g 获取堆顶元素\n-p 打印堆\n-0 退出\n");
while(1)
{
fflush(stdin);
scanf("%s",s);
if(s[1]=='a')
{
scanf("%d",&a[++size]);
addAdjust(a,size);
//printf("-a\n");
}
else if(s[1]=='d')
{
/*deleteAdjust(a);
printf("堆顶元素已经删除成功!");
//printf("-d\n");*/
///*
a[1] = a[size--];
heapAdjust(a,1,size);
//*/
}
else if(s[1]=='g')
{
printf("目前堆顶元素(即最小元素)为:%d\n",a[1]);
//printf("-g\n");
}
else if(s[1]=='p')
{
int i;
for(i=1;i<=size;i++)
printf("%d ",a[i]);
printf("\n");
//printf("-p\n");
}
else if(s[1]=='0')
{
break;
}
else
{
printf("命令错误\n");
printf("请输入相关命令和数据:\n-a 添加数据\n-d 删除堆顶 \n-g 获取堆顶元素\n-p 打印堆\n-0 退出\n");
}
}
printf("操作完成\n");
return 0;
}
#include<stdio.h>
//实现堆的各种操作 加入数据 删除数据 调整堆 获取数据
//为方便编程 数组从1开始 小顶堆
int a[100];
int size = 0;
int c,b;
void swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void addAdjust(int a[],int size)
{
int id = size;
while(id/2!=0&&a[id]<a[id/2])//向上调整直至堆顶
{
swap(&a[id],&a[id/2]);
id = id/2;//id 向上前进
}
}
int max(int a,int b)
{
return a=a>b?a:b;
}
void heapAdjust(int *a,int i,int size)
{
int lchild = 2*i;
int rchild = 2*i+1;
int max = i;
if(lchild<=size&&a[max]>a[lchild])
{
max = lchild;
}
if(rchild<=size&&a[max]>a[rchild])
{
max = rchild;
}
if(max!=i)
{
swap(&a[max],&a[i]);
heapAdjust(a,max,size);
}
else
return;
}
void deleteAdjust(int a[])
{
a[1] = a[size--];
int id = 1;
int child = id*2;
for(;id*2<size;id = child)//保证其至少有左儿子
{
child = id*2;
if(child+1<=size&&a[child]>a[child+1])//在有右儿子的前提下判断谁最小
{
child +=1;
}
if(a[id]>a[child])//若俩儿子中最小值比父节点值小 交换
{
swap(&a[id],&a[child]);
}
else
{
break;
}
}
//id = child 这一步很巧妙的
}
void minDelete(int a[])
{
int id=1;
while(id*2<=size)
{
if(id*2+1<=size&&a[id*2]>a[id*2+1])
{
a[id] = a[id*2+1];
id = id*2+1;
}
else
{
a[id] = a[id*2];
id = id*2;
}
}
if(id!=size)
{
a[id] = a[size];
while(id>=1)
{
if(a[id/2]>a[id])
{
swap(&a[id/2],&a[id]);
id = id/2;
}
else
{
return;
}
}
}
}
int main()
{
char s[3];
printf("请输入相关命令和数据:\n-a 添加数据\n-d 删除堆顶 \n-g 获取堆顶元素\n-p 打印堆\n-0 退出\n");
while(1)
{
fflush(stdin);
scanf("%s",s);
if(s[1]=='a')
{
scanf("%d",&a[++size]);
addAdjust(a,size);
//printf("-a\n");
}
else if(s[1]=='d')
{
/*deleteAdjust(a);
printf("堆顶元素已经删除成功!");
//printf("-d\n");*/
/*
a[1] = a[size--];
heapAdjust(a,1,size);
*/
minDelete(a);
size--;
}
else if(s[1]=='g')
{
printf("目前堆顶元素(即最小元素)为:%d\n",a[1]);
//printf("-g\n");
}
else if(s[1]=='p')
{
int i;
for(i=1;i<=size;i++)
printf("%d ",a[i]);
printf("\n");
//printf("-p\n");
}
else if(s[1]=='0')
{
break;
}
else
{
printf("命令错误\n");
printf("请输入相关命令和数据:\n-a 添加数据\n-d 删除堆顶 \n-g 获取堆顶元素\n-p 打印堆\n-0 退出\n");
}
}
printf("操作完成\n");
return 0;
}
本次试验提供了三个进行堆删除操作的函数 分别利用了不同的方法
前两种都是通过将a[size] 与a[1] 交换或者说覆盖然后自上而下的进行调整,一个采用for循环,一个采用递归方式。
最后一种直接将堆顶默认为空 然后通过比较子树 选择堆顶 然后向下依次延伸 最后跳出循环之后判断 空出来的位置是不是a[size]
如果不是 将a[id] = a[size] 然后再向上进行调整,当然这样的话复杂度是前两种的两倍。
注意此时size是没有减小的