您的位置:首页 > 其它

实现堆的各种操作

2013-10-03 15:52 162 查看

#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是没有减小的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: