问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

C语言数据结构 堆的建立和维护

发布网友 发布时间:2022-04-23 18:19

我来回答

1个回答

热心网友 时间:2023-10-12 16:50

主要函数功能:1、通过输入的数组,建立堆结构
                       2、将堆结构按小顶堆排列
                       3、输入POP命令提取一个顶元素,存放在数组中。
                      (删除顶节点,重新初始化堆结构,重新按小顶堆排列)
                       4、输入PUSH命令将一个数值插入到堆末尾。
                      (新数值插入数组末尾,用新数组重建堆,重新按小顶堆排列)
                       5、打印所有POP提取的顶元素#include<stdio.h>
#include<malloc.h>
#include<string.h>
typedef struct node
{
    int *data;
    struct node *left;
    struct node *right;
    struct node *brother;
    struct node *father;
}NODE;
typedef struct heapTree
{
    int size;
    int *nums;//节点数值对应的数组
    NODE **nodes;//所有的节点指针,用于释放堆
    struct node *rootNode;//根节点
    struct node *lastNode;//从上往下,从左往右数最后一个节点
}HEAP;
HEAP *initHeap(int *nums,int size);//初始化堆
void recom(NODE *lastNode,int b);//重组堆,按小顶堆排列。先和子女比较,再兄弟和子女比较,再父亲和子女比较。
//参数:lastNode最后一个节点; b避免兄弟间无限循环,b=2跳出兄弟,进行父亲与子女比较,首次调用b传值1
void printfHeap(NODE *rootNode);//测试调试使用:遍历并打印堆数值
void freeHeap(HEAP *heap);//释放堆内存
int getRootNode(HEAP *heap);//取出顶元素
void addRootNode(HEAP *heap,int num);//插入节点元素
int main()
{
    int i,m,n,*nums=NULL,*rootNums=NULL,rNumSize=0,xwNum;//xwNum询问数值
    char xwStr[5];//询问字符串POP或PUSH
    HEAP *heap=NULL;
    printf("输入n,m的值:\n");
    scanf("%d%d",&n,&m);
    nums=(int *)malloc(sizeof(int)*n);
    printf("输入%d个数字:\n",n);
    for(i=0;i<n;i++)
        scanf("%d",&nums[i]);
    heap=initHeap(nums,n);
    recom(heap->lastNode,1);
    //printfHeap(heap->rootNode);//测试:顺序打印节点

    printf("等待%d次询问,请输入POP或PUSH命令:\n",m);
    while(1)
    {
        scanf("%s",xwStr);
        if(strcmp(xwStr,"POP")==0)
        {
            rNumSize++;
            if(rootNums==NULL)
                rootNums=(int *)malloc(sizeof(int)*rNumSize);
            else
                rootNums=(int *)realloc(rootNums,sizeof(int)*rNumSize);//扩展原取值的存储内存
            rootNums[rNumSize-1]=getRootNode(heap);//取出顶元素
            //printfHeap(heap->rootNode);//测试:顺序打印节点
        }
        else if(strcmp(xwStr,"PUSH")==0)
        {
            scanf("%d",&xwNum);
            addRootNode(heap,xwNum);//插入新元素
            //printfHeap(heap->rootNode);//测试:顺序打印节点// 插入后重新排序有问题
        }

        m--;
        if(m==0)
            break;
    }
    printf("所有取出的顶端数值为:\n");
    for(i=0;i<rNumSize;i++)
        printf("%d ",rootNums[i]);
    printf("\n");

    return 0;
}
void addRootNode(HEAP *heap,int num)//插入节点元素
{
    int i,*numsSave=NULL,*nums=heap->nums,size=heap->size;
    numsSave=(int *)malloc(sizeof(int)*(size+1));
    for(i=0;i<size;i++)
        numsSave[i]=nums[i];
    nums=NULL;
    numsSave[i]=num;//将新元素添加在数组末尾
    freeHeap(heap);//释放堆内存
    heap=initHeap(numsSave,size+1);//重新初始新的堆
    recom(heap->lastNode,1);//重新小顶堆排列
}
int getRootNode(HEAP *heap)//取出顶元素
{
    int i,*numsSave=NULL,*nums=heap->nums,size=heap->size,rootNum;
    rootNum=*heap->rootNode->data;
    *heap->rootNode->data=nums[size-1];//根节点对应值换成数组最后一位地址值
    numsSave=(int *)malloc(sizeof(int)*(size-1));
    for(i=0;i<size-1;i++)
        numsSave[i]=nums[i];
    nums=NULL;//原数组空间将在freeHeap函数中一并释放
    freeHeap(heap);//释放堆内存
    heap=initHeap(numsSave,size-1);//重新初始新的堆
    recom(heap->lastNode,1);//重新小顶堆排列
    return rootNum;
}
void freeHeap(HEAP *heap)//释放堆内存
{
    int i;
    for(i=0;i<heap->size;i++)//释放所有节点空间
    {
        heap->nodes[i]->data=NULL;
        heap->nodes[i]->brother=NULL;
        heap->nodes[i]->father=NULL;
        heap->nodes[i]->left=NULL;
        heap->nodes[i]->right=NULL;
        free(heap->nodes[i]);
    }
    free(heap->nums);
    heap->nums=NULL;
    heap->nodes=NULL;
    heap->lastNode=NULL;
    heap->rootNode=NULL;
    heap->size=0;
    free(heap);
}
void printfHeap(NODE *rootNode)//遍历并打印堆数值
{
    printf("%d ",*rootNode->data);
    if(rootNode->father==NULL && rootNode->left!=NULL)//根节点
        printfHeap(rootNode->left);
    else if(rootNode->father->left==rootNode && rootNode->father->right!=NULL)//如果第左,那么找右
        printfHeap(rootNode->father->right);
    else if(rootNode->father->right==rootNode && rootNode->brother->left!=NULL)//如果第右,那么找左的左儿子
        printfHeap(rootNode->brother->left);
    else
        printf("\n");
}
HEAP *initHeap(int *nums,int size)
{
    int i;
    NODE *newNode=NULL;
    HEAP *heap=(HEAP *)malloc(sizeof(HEAP));
    heap->rootNode=NULL;
    heap->lastNode=NULL;
    heap->nodes=(NODE **)malloc(sizeof(NODE *)*size);
    heap->nums=nums;
    for(i=0;i<size;i++)
    {
        newNode=(NODE *)malloc(sizeof(NODE));
        heap->nodes[i]=newNode;
        newNode->data=&nums[i];
        newNode->left=NULL;
        newNode->right=NULL;
        newNode->brother=NULL;
        newNode->father=NULL;
        if(heap->rootNode==NULL)
            heap->rootNode=newNode;
        else if(heap->lastNode->father==NULL)//上一个节点为根节点没有兄弟,新节点放在左位置
        {
            heap->lastNode->left=newNode;
            newNode->father=heap->lastNode;
        }
        else if(heap->lastNode->father->left==heap->lastNode)//上一个非根左节点,新节点放兄弟位置
        {
            heap->lastNode->brother=newNode;
            newNode->brother=heap->lastNode;
            newNode->father=heap->lastNode->father;
            newNode->father->right=newNode;
        }
        else if(heap->lastNode->father->right==heap->lastNode)//上一个非根右节点,新节点放兄弟左儿子位置
        {
            heap->lastNode->brother->left=newNode;
            newNode->father=heap->lastNode->brother;
        }
        heap->lastNode=newNode;
    }
    heap->size=size;
    return heap;
}
void recom(NODE *lastNode,int b)//重组堆,按小顶堆排列。先和子女比较,再兄弟和子女比较,再父亲和子女比较。
//参数:lastNode最后一个节点; b避免兄弟间无限循环,b=2跳出兄弟,进行父亲与子女比较
{
    int numSave;
    NODE *minNode=NULL,*fNode=lastNode->father,*bNode=lastNode->brother,*lNode=lastNode->left,*rNode=lastNode->right;
    if(lNode!=NULL)
    {
        minNode=lastNode;
        if(*minNode->data>*lNode->data)
        {
            numSave=*minNode->data;
            *minNode->data=*lNode->data;
            *lNode->data=numSave;
        }
    }
    if(rNode!=NULL)
    {
        if(*minNode->data>*rNode->data)
        {
            numSave=*minNode->data;
            *minNode->data=*rNode->data;
            *rNode->data=numSave;
        }
    }
    if(b==2)
        recom(fNode,1);
    else if(bNode!=NULL)
        recom(bNode,2);
}

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
不想要淘宝原来的帐号,怎么办,可以注销吗~谢谢了,大神帮忙啊 蓝宝石HD6770显卡求鉴定,GPUZ检测数据如下: 健身60公斤,176身高的人,比较瘦,是不是即便经常锻炼,力气也不一定比胳膊... 农村土地什么情况不予发证?如何解决? 共工治水在前还是怒触不周山在前? 共工触山的故事 有什么类似漂流瓶的软件推荐 漂流瓶软件推荐 保险柜密码怎么改 保险柜密码正确但是打不开怎么办 西安水多少钱一顿 西安哪里可以买自来水 用c语言编写一段程序,建立一个顺序表(需要自己输入数据,并插入数据、删除数据)。 喝柠檬水真的会变白吗?为什么? 用c语言编写一段程序,建立一个顺序表,需要自己输入数据,并插入数据,删除数据 C语言:建立一个学生信息数据库 C语言:1.建立含n个数据元素的顺序表并输出该表中各元素的值及顺序表的长度。 紧急求 速度 c语言如何用链表构建数据结构并实现数据的输入和保存? c语言如何创建一个txt文件并写入数据? c语言中如何建立数据库 如何用C语言建立数据库 经常喝柠檬水,真的会让人变白吗? C语言中 如何建立一个储存数据的文件 你有过哪些经历从来没有对人说过? 把王八跟金鱼放到冰箱里结果金鱼对着王八笑了,这是为啥 贺来贤人到底有几个孩子? 电影深海巨鲨里面那个DJ手上戴的那个手表是什么牌子的? 求2012世界末日电影百度云资源_(:3」∠)_ 您好,刚才看到了一条消息,不知是否给我的回答?请确认一下,谢谢! 金融词汇解释,什么叫离岸?? 什么叫做离岸人民币?怎样才可能参与离岸交易? 你喜欢的歌词或现代诗词? C语言编写 数据结构 数据结构(C语言版) 建立二叉树数据怎么输入? C语言写出一个建立并写入数据的二进制文件,文件后缀为.dat。 C语言编写的创建并写入数据,文件路径如何由用户输入? 如何用c语言把生成的数据创建成一个文档? 怎么和电脑多屏互动 多屏互动在哪 找不到多屏互动设备怎么办 windows 7 怎么开启多屏互动? 手机电脑多屏互动怎么用? windows 7 怎么开启多屏互动 电脑怎样实现多屏互动,即一个屏幕两个桌面, win10和电视机怎么多屏互动 初春钓草鱼有什么秘方 电脑跟电视可以实现无线多屏互动吗 春季在水库如何台钓草鱼技巧 苹果8p音量键开到最大还是没声音咋办? 如何与电脑多屏互动 春天如何钓草鱼,如何钓大草鱼 电脑可以多屏互动吗?