发布时间:2025-06-24 20:09:22  作者:北方职教升学中心  阅读量:996


查看堆顶元素

intHeapEmpty(Heap*pHeap){assert(pHeap);returnpHeap->count ==0;}HeapDataType HeapTop(Heap*pHeap){assert(!HeapEmpty(pHeap));returnpHeap->data[1];}

(二)哈夫曼编码实现

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<time.h>#include<string.h>#include<algorithm>#include<unordered_map>#include<vector>using namespace std;#defineFATHER(i)((i)/2)#defineLEFT(i)((i)*2)#defineRIGHT(i)((i)*2+1)typedefstructNode{char*c;intfreq;structNode*lchild,*rchild;}Node;template<typename T>voidSwap(T&a,T&b){T c =a;a =b;b =c;return;}//void swap(Node* a, Node* b) {//	Node* c = a;//	a = b;//	b = c;//	return;//}Node*getNewNode(intfreq,constchar*c){Node*p =(Node*)malloc(sizeof(Node));p->freq =freq;p->c =_strdup(c);p->lchild =p->rchild =NULL;returnp;}voidclear(Node*root){if(root ==NULL)return;clear(root->lchild);clear(root->rchild);free(root);return;}typedefstructheap{Node**data,**__data;intsize,count;}heap;heap*initHeap(intn){heap*p =(heap*)malloc(sizeof(heap));p->__data =(Node**)malloc(sizeof(Node*)*n);p->data =p->__data -1;p->size =n;p->count =0;returnp;}intempty(heap*h){returnh->count ==0;}intfull(heap*h){returnh->count ==h->size;}Node*top(heap*h){if(empty(h))returnNULL;returnh->data[1];}//void up_update(Node** data, int i) {//	while (FATHER(i) >= 1) {//		int ind = i;//		if (data[i]->freq < data[FATHER(i)]->freq) {//			swap(data[i], data[FATHER(i)]);//}//		if (ind == i) break;//		i = FATHER(i);//	}//	return;//}voidup_update(Node**data,inti){while(i >1&&data[i]->freq <data[FATHER(i)]->freq){Swap(data[i],data[FATHER(i)]);i =FATHER(i);}return;}voiddown_update(Node**data,inti,intn){while(LEFT(i)<=n){intind =i,l =LEFT(i),r =RIGHT(i);if(data[i]->freq >data[l]->freq)ind =l;if(RIGHT(i)<=n &&data[r]->freq <data[ind]->freq)ind =r;if(ind ==i)break;Swap(data[ind],data[i]);i =ind;}return;}voidpush(heap*h,Node*node){if(full(h))return;h->count +=1;h->data[h->count]=node;up_update(h->data,h->count);return;}voidpop(heap*h){if(empty(h))return;h->data[1]=h->data[h->count];h->count -=1;down_update(h->data,1,h->count);return;}voidclearHeap(heap*h){if(h ==NULL)return;free(h->__data);free(h);return;}Node*build_huffman_tree(Node**nodeArr,intn){heap*h =initHeap(n);for(inti =0;i <n;i++){push(h,nodeArr[i]);}Node*node1,*node2;intfreq;for(inti =1;i <n;i++){node1 =top(h);pop(h);node2 =top(h);pop(h);freq =node1->freq +node2->freq;Node*node3 =getNewNode(freq,"0");node3->lchild =node1;node3->rchild =node2;push(h,node3);}returnh->data[1];}voidoutput(Node*root){if(root ==NULL)return;output(root->lchild);//if (root->lchild == NULL && root->rchild == NULL) printf("%s : %dn",root->c,root->freq);output(root->rchild);return;}charcharArr[100];unordered_map<char*,char*>h;voidextract_huffman_code(Node*root,inti){charArr[i]=0;if(root->lchild ==NULL&&root->rchild ==NULL){h[root->c]=_strdup(charArr);return;}charArr[i -1]='0';extract_huffman_code(root->lchild,i +1);charArr[i -1]='1';extract_huffman_code(root->rchild,i +1);return;}intmain(){#defineMAX_CHAR26//1.首先用一个数组读取相关字符串及其频率Node**charArr =(Node**)malloc(sizeof(Node*)*MAX_CHAR);chararr[10];intfreq;for(inti =0;i <MAX_CHAR;i++){scanf("%s%d",arr,&freq);charArr[i]=getNewNode(freq,arr);}//2.建立哈夫曼树Node*root =build_huffman_tree(charArr,MAX_CHAR);//3.提取哈夫曼编码进入unordered_mapextract_huffman_code(root,1);//4.将unordered_map转换成vector排序,可以按照字典序输出编码vector<pair<char*,char*>>v(h.begin(),h.end());sort(v.begin(),v.end(),[&](constpair<char*,char*>&a,constpair<char*,char*>&b){returnstrcmp(a.first,b.first)<0;});for(auto&x :v){printf("%s : %sn",x.first,x.second);}return0;}

在这里插入图片描述

结束语

关注博主的专栏,博主会分享更多的数据结构知识!
🐾博主的数据结构专栏

在这里插入图片描述

堆)详解
  • 一、树

    树的物理结构和逻辑结构上都是树形结构

    (一)树的性质

    • ⼦树是不相交的
    • 除了根结点外,每个结点有且仅有⼀个⽗结点
    • ⼀棵N个结点的树有N-1条边

    (二)树的种类

    树按照根节点的分支来分,可以分为二叉树和多叉树。堆的结构定义

    下面通过宏函数来实现交换,可以使得交换简便,或者用指针也行。层序遍历

  • (2)二叉树结点个数
  • (3) ⼆叉树叶⼦结点个数
  • (4) 二叉树第k层结点个数
  • (5)二叉树的深度/高度
  • (6)⼆叉树查找值为x的结点
  • (7)二叉树销毁
  • (8)判断二叉树是否为完全二叉树
  • 二、出堆操作
    voidHeapPop(Heap*pHeap){assert(pHeap);assert(!HeapEmpty(pHeap));pHeap->data[1]=pHeap->data[pHeap->count];Heap_DOWN_Update(pHeap,1);pHeap->count -=1;return;}

    8、可以是空树,或者由一个根节点和左、

    在这里插入图片描述

    完全N叉树

    除了最后一层外,每一层都被完全填满,并且最后一层所有节点都尽量靠左排列。入堆操作

  • 6、向下调整操作
    voidHeap_DOWN_Update(Heap*pHeap,inti){assert(pHeap);intsize =pHeap->count -1;while(LEFT(i)<=size){intl =LEFT(i),r =RIGHT(i),ind =i;if(pHeap->data[ind]>pHeap->data[l])ind =l;if(r <=size &&pHeap->data[ind]>pHeap->data[r])ind =r;if(ind ==i)break;SWAP(pHeap->data[i],pHeap->data[ind]);i =ind;}return;}

    5、堆

    堆的物理结构是一段连续空间,但是逻辑机构是树形结构

    (一)堆的实现

    1、

    bool BinaryTreeComplete(BTNode*root){queue<BTNode*>q;BinaryTreePushQueue(root,q);while(!q.empty()){if(q.front()!=NULL)q.pop();elsebreak;}while(!q.empty()){if(q.front()==NULL)q.pop();elsereturnfalse;}returntrue;}voidBinaryTreePushQueue(BTNode*root,queue<BTNode*>&q){vector<vector<BTNode*>>v;BinaryNodePushVector(root,v,0);for(inti =0;i <v.size();i++){for(autox :v[i]){q.push(x);}}return;}voidBinaryNodePushVector(BTNode*root,vector<vector<BTNode*>>&v,intk){if(v.size()==k)v.push_back(vector<BTNode*>());if(root ==NULL){v[k].push_back(NULL);//如果不处理空结点,取消这步即可return;}v[k].push_back(root);BinaryNodePushVector(root->left,v,k +1);BinaryNodePushVector(root->right,v,k +1);return;}

    二、

    typedefintHeapDataType;typedefstructHeap{HeapDataType*__data;HeapDataType*data;intcount;intcapacity;}Heap;
    #defineSWAP(a ,b){HeapDataType c =(a);(a)=(b);(b)=(c);}

    2、堆的初始化

    用偏移量的方式,节约了内存。堆的初始化

  • 3、入堆操作
    voidHeapPush(Heap*pHeap,HeapDataType x){assert(pHeap);HeapCheckCapacity(pHeap);pHeap->data[pHeap->count +1]=x;DG_Heap_UP_Update(pHeap,pHeap->count +1);pHeap->count +=1;return;}

    6、二叉树功能实现

    • (1)前序、

      数据结构:树形结构(树、中序、堆的判空、二叉树功能实现

      (1)前序、

      voidBinaryTreeDestory(BTNode**root){if(*root ==NULL)return;BinaryTreeDestory(&((*root)->left));BinaryTreeDestory(&((*root)->right));free(*root);*root =NULL;return;}
      (8)判断二叉树是否为完全二叉树

      这段代码是老夫目前想了许久,觉得很有不错的代码,先不考虑它的实现复杂度以及简洁程度,它实现的功能不错,可以将二叉树包括空结点放在队列之中,自己觉得很好,哈哈,也许你没看到这句,那我就放心了。右子树组成。

      在这里插入图片描述

      (三)二叉树的实现

      1、向下调整操作

    • 5、堆的销毁
      voidHeapDestroy(Heap*pHeap){assert(pHeap);free(pHeap->__data);pHeap->data =NULL;pHeap->__data =NULL;pHeap->capacity =0;pHeap->count =0;return;}

      9、

      多叉树

      多叉树(Multiway Tree)
      定义:每个节点可以有多个子节点的树结构,节点子节点的数量没有限制。向上调整操作

    • 4、堆
      • (一)堆的实现
        • 1、出堆操作
        • 8、堆的扩容
          voidHeapCheckCapacity(Heap*pHeap){assert(pHeap);if(pHeap->capacity ==pHeap->count){HeapDataType*temp =(HeapDataType*)realloc(pHeap->__data,2*pHeap->capacity *sizeof(HeapDataType));if(!temp){perror("Heap Realloc Fail!");exit(1);}pHeap->__data =temp;pHeap->capacity *=2;}return;}

          7、

          二叉树

          二叉树(Binary Tree)
          定义:每个节点最多有两个子节点的树结构。二叉树结构定义

          用 typedef 可以使得后面的使用范围更广

          typedefintBTDataType;typedefstructBinaryTreeNode{BTDataType data;structBinaryTreeNode*left;structBinaryTreeNode*right;}BTNode;

          2、二叉树结构定义

        • 2、中序、堆的扩容
        • 7、堆的判空、堆的结构定义
        • 2、

          树按照结点的特性来观察,又可以有满N叉树和完全N叉树

          满N叉树

          满N叉树是一种深度为K的二叉树,其中每一层的节点数都达到了该层能有的最大节点数。向上调整操作

          可以使用递归或者是循环来实现向上调整

          voidHeap_UP_Update(Heap*pHeap,inti){assert(pHeap);while(FATHER(i)>=1&&pHeap->data[FATHER(i)]>pHeap->data[i]){SWAP(pHeap->data[FATHER(i)],pHeap->data[i]);i =FATHER(i);}return;}voidDG_Heap_UP_Update(Heap*pHeap,inti){assert(pHeap);if(FATHER(i)<1)return;if(pHeap->data[FATHER(i)]>pHeap->data[i]){SWAP(pHeap->data[FATHER(i)],pHeap->data[i]);i =FATHER(i);DG_Heap_UP_Update(pHeap,i);}return;}

          4、后序、查看堆顶元素

      • (二)哈夫曼编码实现
        • 结束语