学习来源:
数据结构与算法基础(青岛大学-王卓)
地址:
https://www.bilibili.com/video/BV1nJ411V7bd?p=22&spm_id_from=pageDriver
背景:
实现视频里老师的伪代码,并不完全一样,但基本雷同。
更新
2021/10/8
第一次发布
代码:
- 栈的实现(作为工具)
Stack.h
#ifndef _STACK_H_ #define _STACK_H_ //Stack object. typedef struct Stack *Stack; //Your show function pointer. typedef void (*Fun_Stack)(void *); //Get current stack length. //The "s" is the stack object. unsigned GetLen_Stack(Stack s); //Create a new stack. //This "DataSize" is how much the byte number of your data type. //This "StackLength" represents the length of your array. //This function will return the object of stack if it's running successfully Stack Create_Stack(unsigned DataSize); //Destroy the stack. //The "s" is the stack object. void Destroy_Stack(Stack s); //Push an element to the stack top. //The "Elem" is elemet pointer which you need to send. //The "s" is the stack object. void Push_Stack(Stack s, void *Elem); //Show all element's value on console. //The "s" is the stack object. //The "f" is your function, it will execute f for stack's len times. void Show_Stack(Stack s, Fun_Stack f); //POP a element. //The "s" is the stack object. //The "ret" is pop elememt's value. void POP_Stack(Stack s, void *ret); //Clear stack of s. void Clear_Stack(Stack s); int isEmpty_Stack(Stack s); #endif
Stack.c
#include#include #include #include "Stack.h" #include "CommonFunc.h" #define StackbaseLen 20 struct Stack { void *ESP;//The stack's top. void *EBP;//The stack's tail. void *Data;//Stack memory's address. unsigned DataSize;//Stack element's type size. unsigned StackLength;//Stack max length. }; static int isFull_Stack(Stack s); static void Expand_Stack(Stack s); //Expand the stack max length when the elements' amount have out of limit. static void Expand_Stack(Stack s) { NULLPointOut(s, "Expand_Stack", "s"); unsigned len = GetLen_Stack(s); unsigned DataSize = s->DataSize; void *Data = s->Data; unsigned NewStackLength = s->StackLength + StackbaseLen; void *NewData = malloc(NewStackLength * DataSize); NULLMallocOut(NewData, "Expand_Stack", "NewData"); void *NewEBP = Index(NewData, (int)NewStackLength, DataSize); void *NewESP = Index(NewData, (int)(NewStackLength - len), DataSize); memcpy(NewESP, s->ESP, len * DataSize); s->StackLength = NewStackLength; s->Data = NewData; s->EBP = NewEBP; s->ESP = NewESP; free(Data); return; } void Clear_Stack(Stack s) { NULLPointOut(s, "Clear_Stack", "s"); s->ESP = s->EBP; return; } void POP_Stack(Stack s, void *ret) { NULLPointOut(s, "POP_Stack", "s"); NULLPointOut(ret, "POP_Stack", "ret"); unsigned typeSize = s->DataSize; if(isEmpty_Stack(s)) { memset(ret, 0, typeSize); return; } memcpy(ret, s->ESP, typeSize); s->ESP = PointerInc(s->ESP, typeSize); return; } void Show_Stack(Stack s, Fun_Stack f) { NULLPointOut(s, "Show_Stack", "s"); long len = GetLen_Stack(s); void *tmp = s->ESP; unsigned typeSize = s->DataSize; puts("------------------"); printf("length = %ld, DataSize = %un", len, typeSize); long i; for(i = 0; i < len; i++) { f(tmp); tmp = PointerInc(tmp, typeSize); } puts(""); puts(""); return; } //Get current stack length. //The "s" is the stack object. unsigned GetLen_Stack(Stack s) { NULLPointOut(s, "GetLen_Stack", "s"); return (unsigned)PointerSub(s->EBP, s->ESP, s->DataSize); } static int isFull_Stack(Stack s) { NULLPointOut(s, "isFull_Stack", "s"); //Full return 1 else return 0; return GetLen_Stack(s) == s->StackLength ? 1 : 0; } int isEmpty_Stack(Stack s) { NULLPointOut(s, "isEmpty_Stack", "s"); //Empty return 1 else return 0; return GetLen_Stack(s) == 0 ? 1 : 0; } void Push_Stack(Stack s, void *Elem) { NULLPointOut(s, "Push_Stack", "s"); NULLPointOut(Elem, "Push_Stack", "Elem"); while(isFull_Stack(s)) { Expand_Stack(s); } s->ESP = PointerDec(s->ESP, s->DataSize); memcpy(s->ESP, Elem, s->DataSize); return; } Stack Create_Stack(unsigned DataSize) { if(DataSize == 0) { return NULL; } unsigned StackLength = StackbaseLen; Stack s = (Stack)malloc(sizeof(struct Stack)); NULLMallocOut(s, "Create_Stack", "s"); s->Data = malloc(DataSize * StackLength); NULLMallocOut(s->Data, "Create_Stack", "Data"); //The stack's tail is memory's higher address. //The stack's top is memory's lower address. s->EBP = Index(s->Data, (int)StackLength, DataSize); s->ESP = Index(s->Data, (int)StackLength, DataSize); s->DataSize = DataSize; s->StackLength = StackLength; return s; } void Destroy_Stack(Stack s) { NULLPointOut(s, "Destroy_Stack", "s"); NULLPointOut(s->Data, "Destroy_Stack", "Data"); free(s->Data); free(s); return; }
- 普通常用工具类(降低代码复用)
CommonFunc.h
#ifndef _COMMONFUNC_H_ #define _COMMONFUNC_H_ //If p equal null, exit program and pop a err message. //The parameter 'func' is error function name. //The paremeter 'element' is problem variables. void NULLPointOut(void *p, char *func, char *element); void NULLMallocOut(void *p, char *func, char *element); //Index array. //The "P" is array's head pointer. //The "index" is your element position in array. //The "DataSize" is element's type size. //It returns the address of the element you are looking for. void * Index(void *P, int index, unsigned DataSize); //Pointer plus plus and pointer sub sub. //The "P" is array's head pointer. //The "DataSize" is element's type size. void * PointerInc(void *P, unsigned DataSize); void * PointerDec(void *P, unsigned DataSize); //Get the distance between A and B. //return (A - B) / DataSize //The "DataSize" is element's type size. long PointerSub(void *A, void *B, unsigned DataSize); #endif
CommonFunc.c
#include#include #include #include "CommonFunc.h" long PointerSub(void *A, void *B, unsigned DataSize) { NULLPointOut(A, "PointerSub", "A"); NULLPointOut(B, "PointerSub", "B"); if(DataSize == 0) { puts("PointerSub ERROR: Divide zero error"); exit(-1); } return ((char *)A - (char *)B) / DataSize; } void * PointerDec(void *P, unsigned DataSize) { NULLPointOut(P, "PointerDec", "P"); char *c = (char *)P; c = c - DataSize; return c; } void * PointerInc(void *P, unsigned DataSize) { NULLPointOut(P, "PointerInc", "P"); char *c = (char *)P; c = c + DataSize; return c; } void NULLPointOut(void *p, char *func, char *element) { if(func == NULL) { puts("NULLPointOut ERROR: NULL point exception 'func'"); exit(-1); } else if(element == NULL) { puts("NULLPointOut ERROR: NULL point exception 'element'"); exit(-1); } if(p == NULL) { printf("%s ERROR: NULL point exception '%s'n", func, element); exit(-1); } return; } void NULLMallocOut(void *p, char *func, char *element) { NULLPointOut(func, "NULLMallocOut", "func"); NULLPointOut(element, "NULLMallocOut", "element"); if(p == NULL) { printf("%s ERROR: Malloc error '%s'n", func, element); exit(-1); } return; } void * Index(void *P, int index, unsigned DataSize) { NULLPointOut(P, "Index", "P"); char *c = (char *)P; c = c + index * (int)DataSize; return c; }
- 哈夫曼树的实现
Huffman.h
#ifndef _HUFFMAN_H_ #define _HUFFMAN_H_ typedef struct Huffman *Huffman; //Create a Huffman tree that have "warrLen" leaf nodes. Huffman Create_Huffman(int warr[], unsigned warrLen); //Destroy Huffman tree, "hfmP" will be set NULL. void Destroy_Huffman(Huffman *hfmP); //Show Huffman tree nodes. void Show_Huffman(Huffman hfm); #endif
Huffman.c
#include#include #include #include "Huffman.h" #include "CommonFunc.h" typedef struct { int weight;//Each node's weright. int parent;//Each node's parent node's index. int left;//Each node's left child node's index. int right;//Each node's right child node's index. } HNode; struct Huffman { HNode *HNArr;//Huffman tree's nodes. unsigned HuffmanLen;//Huffman tree length. int *HNArrP;//As a tool to soft the tree from weight. }; //Get the available node amount from Huffman tree "hfm". static unsigned GetNodeLen_Huffman(Huffman hfm); //Fill the Huffman tree. static void FillHuffman(Huffman hfm); //Sort Huffman tree by weight. static void Sort_Huffman(Huffman hfm); //Show Huffman tree nodes' weight after sort. static void ShowSort_Huffman(Huffman hfm); //Swap static void Swap_Huffman(int *a, int *b); //Get left and right child write into "L" and "R". static int GetChildren_Huffman(Huffman hfm, int *L, int *R); static int GetChildren_Huffman(Huffman hfm, int *L, int *R) { NULLPointOut(hfm, "GetChildren_Huffman", "hfm"); NULLPointOut(L, "GetChildren_Huffman", "L"); NULLPointOut(R, "GetChildren_Huffman", "R"); HNode *HNArr = hfm->HNArr; int *HNArrP = hfm->HNArrP; unsigned n = GetNodeLen_Huffman(hfm); int arr[2]; unsigned j = 0; unsigned i; for(i = 0; i < n && j < 2; i++) { if(HNArr[HNArrP[i]].parent == -1) { arr[j] = HNArrP[i]; j++; } } if(j < 2) { return 0; } *L = arr[0]; *R = arr[1]; return 1; } static void Swap_Huffman(int *a, int *b) { NULLPointOut(a, "Swap_Huffman", "a"); NULLPointOut(b, "Swap_Huffman", "b"); int tmp; tmp = *a; *a = *b; *b = tmp; return; } static void ShowSort_Huffman(Huffman hfm) { NULLPointOut(hfm, "ShowSort_Huffman", "hfm"); NULLPointOut(hfm->HNArrP, "ShowSort_Huffman", "HNArrP"); HNode *HNArr = hfm->HNArr; unsigned HuffmanLen = hfm->HuffmanLen; int *HNArrP = hfm->HNArrP; unsigned i; for(i = 0; i < HuffmanLen; i++) { printf("%d ", HNArr[HNArrP[i]].weight); } puts(""); return; } void Show_Huffman(Huffman hfm) { NULLPointOut(hfm, "Show_Huffman", "hfm"); HNode *HNArr = hfm->HNArr; unsigned HuffmanLen = hfm->HuffmanLen; printf("index tweight tparent tleft trightn"); unsigned i; for(i = 0; i < HuffmanLen; i++) { printf( "%u t%d t%d t%d t%dn", i, HNArr[i].weight, HNArr[i].parent, HNArr[i].left, HNArr[i].right ); } puts(""); } static void Sort_Huffman(Huffman hfm) { NULLPointOut(hfm, "Sort_Huffman", "hfm"); int *HNArrP = hfm->HNArrP; HNode *HNArr = hfm->HNArr; unsigned n = GetNodeLen_Huffman(hfm); unsigned i, j; for(j = 0; j < n - 1; j++) { for(i = 0; i < n - j - 1; i++) { if(HNArr[HNArrP[i]].weight > HNArr[HNArrP[i + 1]].weight) { Swap_Huffman(&HNArrP[i], &HNArrP[i + 1]); } } } return; } static void FillHuffman(Huffman hfm) { NULLPointOut(hfm, "FullHuffman", "hfm"); HNode *HNArr = hfm->HNArr; int L, R, ret; unsigned n; Sort_Huffman(hfm); ret = GetChildren_Huffman(hfm, &L, &R); while(ret) { n = GetNodeLen_Huffman(hfm); HNArr[n].left = L; HNArr[n].right = R; HNArr[n].weight = HNArr[L].weight + HNArr[R].weight; HNArr[L].parent = (int)n; HNArr[R].parent = (int)n; Sort_Huffman(hfm); ret = GetChildren_Huffman(hfm, &L, &R); } return; } static unsigned GetNodeLen_Huffman(Huffman hfm) { NULLPointOut(hfm, "GetNodeLen_Huffman", "hfm"); HNode *HNArr = hfm->HNArr; unsigned n = hfm->HuffmanLen; unsigned i; for(i = 0; i < n && HNArr[i].weight != -1; i++); return i; } Huffman Create_Huffman(int warr[], unsigned warrLen) { NULLPointOut(warr, "Create_Huffman", "warr"); if(warrLen == 0) { return NULL; } unsigned HuffmanLen = 2 * warrLen - 1; HNode *HNArr = (HNode *)malloc(sizeof(HNode) * HuffmanLen); NULLMallocOut(HNArr, "Create_Huffman", "HNArr"); int *HNArrP = (int *)malloc(sizeof(int) * HuffmanLen); NULLMallocOut(HNArrP, "Create_Huffman", "HNArrP"); Huffman hfm = (Huffman)malloc(sizeof(struct Huffman)); NULLMallocOut(hfm, "Create_Huffman", "hfm"); memset(HNArr, -1, sizeof(HNode) * HuffmanLen); unsigned i; for(i = 0; i < warrLen; i++) { HNArr[i].weight = warr[i]; } for(i = 0; i < HuffmanLen; i++) { HNArrP[i] = (int)i; } hfm->HNArr = HNArr; hfm->HuffmanLen = HuffmanLen; hfm->HNArrP = HNArrP; FillHuffman(hfm); return hfm; } void Destroy_Huffman(Huffman *hfmP) { NULLPointOut(hfmP, "Destroy_Huffman", "hfmP"); NULLPointOut((*hfmP)->HNArr, "Destroy_Huffman", "HNArr"); NULLPointOut((*hfmP)->HNArrP, "Destroy_Huffman", "HNArrP"); free((*hfmP)->HNArr); free((*hfmP)->HNArrP); free(*hfmP); *hfmP = NULL; return; }
- 哈夫曼编码实现
HuffmanCode.h
#ifndef _HUFFMANCODE_H_ #define _HUFFMANCODE_H_ typedef struct HuffmanCode *HuffmanCode; HuffmanCode Create_HuffmanCode(char str[]); void Show_HuffmanCode(HuffmanCode hc); void Destroy_HuffmanCode(HuffmanCode *hcp); char * Coder_HuffmanCode(HuffmanCode hc, char *str); char * UNCoder_HuffmanCode(HuffmanCode hc, char *str); #endif
HuffmanCode.c
#include#include #include #include "CommonFunc.h" #include "Huffman.h" #include "HuffmanCode.h" #include "Stack.h" typedef struct { int weight;//Each node's weright. int parent;//Each node's parent node's index. int left;//Each node's left child node's index. int right;//Each node's right child node's index. } HNode; struct Huffman { HNode *HNArr;//Huffman tree's nodes. unsigned HuffmanLen;//Huffman tree length. int *HNArrP;//As a tool to soft the tree from weight. }; typedef struct Huffman *Huffman; struct HuffmanCode { Huffman hf;//Huffman tree. char *leaf;//Huffman tree's leafs. unsigned leafLen;//Leaf quality. }; static int IsExist_HuffmanCode(HuffmanCode hc, char c); static void DoCode_HuffmanCode(HNode *HNArr, int index, Stack s); static char * UNDoCode_HuffmanCode(char *str, Huffman hf, int *index); void func(void *a) { NULLPointOut(a, "func", "a"); char *c = a; printf("%c", *c); return; } static char * UNDoCode_HuffmanCode(char *str, Huffman hf, int *index) { NULLPointOut(str, "UNDoCode_HuffmanCode", "str"); NULLPointOut(hf, "UNDoCode_HuffmanCode", "hf"); NULLPointOut(index, "UNDoCode_HuffmanCode", "index"); HNode *HNArr = hf->HNArr; unsigned HuffmanLen = hf->HuffmanLen; HNode *tmp = &HNArr[HuffmanLen - 1]; while(*str != ' ') { if(*str == '0') { *index = tmp->left; tmp = &HNArr[*index]; } else if(*str == '1') { *index = tmp->right; tmp = &HNArr[*index]; } str++; if(tmp->left < 0 && tmp->right < 0) { return str; } } return NULL; } char * UNCoder_HuffmanCode(HuffmanCode hc, char *str) { NULLPointOut(hc, "UNCoder_HuffmanCode", "hc"); NULLPointOut(str, "UNCoder_HuffmanCode", "str"); size_t strLen = strlen(str); if(strLen == 0) { return NULL; } Stack s = Create_Stack(sizeof(char)); if(!isEmpty_Stack(s)) { Clear_Stack(s); } Huffman hf = hc->hf; char *leaf = hc->leaf; int index; while(str != NULL) { str = UNDoCode_HuffmanCode(str, hf, &index); if(str != NULL) { Push_Stack(s, &leaf[index]); } } unsigned Len = GetLen_Stack(s); char *carr = (char *)malloc(sizeof(char) * Len + 1); unsigned i; for(i = 0; i < Len; i++) { POP_Stack(s, &carr[i]); } Destroy_Stack(s); return carr; } static void DoCode_HuffmanCode(HNode *HNArr, int index, Stack s) { NULLPointOut(HNArr, "DoCode_HuffmanCode", "HNArr"); NULLPointOut(s, "DoCode_HuffmanCode", "s"); int parentIndex; int parentLeftIndex; int parentRightIndex; char c; while((parentIndex = HNArr[index].parent) != -1) { parentLeftIndex = HNArr[parentIndex].left; parentRightIndex = HNArr[parentIndex].right; if(&HNArr[index] == &HNArr[parentLeftIndex]) { c = '0'; Push_Stack(s, &c); } else if(&HNArr[index] == &HNArr[parentRightIndex]) { c = '1'; Push_Stack(s, &c); } else { puts("ERROR !!!!!!!!!!!!!!!!"); puts("ERROR !!!!!!!!!!!!!!!!"); puts("ERROR !!!!!!!!!!!!!!!!"); exit(-1); } index = parentIndex; } return; } static int IsExist_HuffmanCode(HuffmanCode hc, char c) { NULLPointOut(hc, "IsExist_HuffmanCode", "hc"); char *leaf = hc->leaf; unsigned leafLen = hc->leafLen; unsigned i; for(i = 0; i < leafLen; i++) { if(leaf[i] == c) { return (int)i; } } return -1; } char * Coder_HuffmanCode(HuffmanCode hc, char *str) { NULLPointOut(hc, "Coder_HuffmanCode", "hc"); NULLPointOut(str, "Coder_HuffmanCode", "str"); size_t strLen = strlen(str); if(strLen == 0) { return NULL; } Stack s = Create_Stack(sizeof(char)); if(!isEmpty_Stack(s)) { Clear_Stack(s); } Huffman hf = hc->hf; //char *leaf = hc->leaf; //unsigned leafLen = hc->leafLen; HNode *HNArr = hf->HNArr; int index; size_t i; for(i = 0; i < strLen; i++) { index = IsExist_HuffmanCode(hc, str[i]); if(index < 0) { return NULL; } else { DoCode_HuffmanCode(HNArr, index, s); } } // Show_Stack(s, func); unsigned len = GetLen_Stack(s); char *codeArr = (char *)malloc(len * sizeof(char) + 1); for(i = 0; i < len && !isEmpty_Stack(s); i++) { POP_Stack(s, &codeArr[i]); } codeArr[i] = ' '; Destroy_Stack(s); return codeArr; } void Destroy_HuffmanCode(HuffmanCode *hcp) { NULLPointOut(hcp, "Destroy_HuffmanCode", "hcp"); NULLPointOut(*hcp, "Destroy_HuffmanCode", "hc"); Destroy_Huffman(&((*hcp)->hf)); free((*hcp)->leaf); *hcp = NULL; return; } void Show_HuffmanCode(HuffmanCode hc) { NULLPointOut(hc, "Show_HuffmanHNC", "hc"); unsigned leafLen = hc->leafLen; char *leaf = hc->leaf; Huffman hf = hc->hf; puts("--------------------------------"); unsigned i; for(i = 0; i < leafLen; i++) { printf("%c ", leaf[i]); } puts("n"); Show_Huffman(hf); return; } HuffmanCode Create_HuffmanCode(char str[]) { NULLPointOut(str, "Create_HuffmanCode", "str"); Stack s = Create_Stack(sizeof(char)); if(!isEmpty_Stack(s)) { Clear_Stack(s); } size_t len = strlen(str); unsigned c[256]; memset(c, 0, sizeof(c)); size_t i; for(i = 0; i < len; i++) { if(c[(int)str[i]] == 0) { Push_Stack(s, &str[i]); } c[(int)str[i]]++; } unsigned leafLen = GetLen_Stack(s); char *leaf = (char *)malloc(leafLen * sizeof(char)); NULLMallocOut(leaf, "Create_Stack", "leaf"); int weight[leafLen]; for(i = 0; i < leafLen && !isEmpty_Stack(s); i++) { POP_Stack(s, &leaf[i]); weight[i] = (int)c[(int)leaf[i]]; } Huffman hf = Create_Huffman(weight, leafLen); HuffmanCode hc = (HuffmanCode)malloc(sizeof(struct HuffmanCode)); NULLMallocOut(hc, "Create_Huffman", "hc"); hc->hf = hf; hc->leaf = leaf; hc->leafLen = leafLen; Destroy_Stack(s); return hc; }
- 主函数执行代码
#include#include #include #include "CommonFunc.h" #include "Huffman.h" #include "HuffmanCode.h" #include "Stack.h" int main(void) { HuffmanCode hc = Create_HuffmanCode("abcbdcbbbcccabefggh"); //创建哈夫曼编码规则 Show_HuffmanCode(hc); char *coder = Coder_HuffmanCode(hc, "abcbdcbbbcccabefgghhhh");//编码 puts(coder); char *uncoder = UNCoder_HuffmanCode(hc, coder);//解码 puts(uncoder); //销毁所有堆内存 Destroy_HuffmanCode(&hc); free(coder); free(uncoder); return 0; }



