Data structure implementation in C Language
1. Basic Concepts
A. Path and path length
If there is a node sequence k1, k2,... in a tree ,......, Kj, so that ki is the parent of ki + 1 (1 <= I <j), this node sequence is the path from k1 to kj.
The number of branches passing through from k1 to kj is the path length between the two points, which is equal to the number of nodes on the path minus 1.
B. node ownership and weighted path length
In many applications, the node in the tree is often assigned a real number with a certain meaning. We call this real number as the right of the node, (For example, the blue number in the following tree indicates the right of the node)
The length of the weighted path of a node must be the product of the length of the path from the root node to the node and the permission on the node.
C. The length of the tree's weighted path
The length of a tree's weighted path is defined as the sum of the length of the weighted path of all leaf nodes in the tree. The formula is:
N indicates the number of leaf nodes, and wi and li indicate the weight of the leaf node ki and the path length between the root node and the ki respectively.
For example, WPL = 9x2 + 12x2 + 15x2 + 6x3 + 3x4 + 5x4 = 122
D. User tree
The Harman tree is also called the optimal binary tree. It is the binary tree with the minimum length of WPL in all the Binary Trees composed of n weighted leaf nodes.
For example, it is a user tree.
2. Construct a user-defined tree
Assume that there are n weights, then the constructed Harman tree has n leaf nodes. Set n weights to w1, w2 ,... And wn, then the construction rule of the Harman tree is:
(1) convert w1, w2 ,..., Wn is regarded as a forest with n trees (each tree has only one node );
(2) Select the tree with the smallest weight of the two root nodes in the forest and combine them as the left and right subtree of a new tree, the root node weights of the new tree are the sum of the left and right child root node weights;
(3) Delete the two trees selected from the forest and add the new trees to the forest;
(4) Repeat steps (2) and (3) until there is only one tree left in the forest, and the tree is the hand tree obtained.
For example, to construct a user-defined tree with six weighted leaf nodes, perform the following steps:
Note: In order to make the structure of the Harman tree as unique as possible, it is usually stipulated that the right of the left sub-root node of each node in the generated Harman tree is less than or equal to the right sub-root node.
The specific algorithm is as follows:
/*** Create a Harman tree */PtrHuffman createHuffmanTree (ElemType arr []) {PtrHuffman ptrArr [LENGTH]; PtrHuffman ptr, pRoot = NULL; for (int I = 0; I <LENGTH; I ++) {// initialize the struct pointer array. Each element in the array is a struct pointer type ptr = (PtrHuffman) malloc (sizeof (HuffmanTreeNode )); ptr-> data = arr [I]; ptr-> left = ptr-> right = NULL; ptrArr [I] = ptr;} for (I = 1; I <LENGTH; I ++) {// create a Harman tree using n-1 cycles // k1 indicates the subscript of the root node with the minimum weight in the forest, k2 is the minimum subscript int k1 =-1, k2; For (int j = 0; j <LENGTH; j ++) {if (ptrArr [j]! = NULL & k1 =-1) {k1 = j; continue;} if (ptrArr [j]! = NULL) {k2 = j; break ;}// assign the minimum value pointed to by the pointer in the pointer array to the index number k1, the next small value is assigned to for (j = k2; j <LENGTH; j ++) {if (ptrArr [j]! = NULL) {if (ptrArr [j]-> data <ptrArr [k1]-> data) {k2 = k1; k1 = j ;} else if (ptrArr [j]-> data <ptrArr [k2]-> data) {k2 = j ;}}} // create a new tree from the minimum and secondary least weights trees. The pRoot points to the root node pRoot = (PtrHuffman) malloc (sizeof (HuffmanTreeNode )); pRoot-> data = ptrArr [k1]-> data + ptrArr [k2]-> data; pRoot-> left = ptrArr [k1]; pRoot-> right = ptrArr [k2]; ptrArr [k1] = pRoot; // assign the pointer to the new tree to ptrArr pointer array, position 1, ptrArr [k2] = NULL; // The k2 position is Blank} return pRoot ;}
3. Harman Encoding
In telegraph communication, a message is transmitted in a sequence of 0 and 1 in binary. Each character corresponds to a binary code. To shorten the total length of the message, an unequal length encoding method is used to construct a user tree,
Assign the occurrence frequency of each character as the weight of the character node to the leaf node. The left and right branches of each branch node are encoded with 0 and 1 respectively, from the root node to the path of each leaf node.
The 0 and 1 encoding sequences of the branches are the binary codes of the leaf node. As shown in the preceding figure, the Haffman encoding is as follows:
A is encoded as: 00
B is encoded as: 01
C encoding: 100
D encoding: 1010
E is encoded as: 1011
F is encoded as: 11
4. Operation of the Harman tree
As an example of the above example, we use a detailed program to demonstrate the operation operations of the table store:
/** User tree encoding **/# include <stdio. h> # include <stdlib. h> # define LENGTH 6 typedef int ElemType; typedef struct HuffmanTreeNode {ElemType data; // the weight of the node in the Harman tree struct HuffmanTreeNode * left; struct HuffmanTreeNode * right;} HuffmanTreeNode, * PtrHuffman;/*** create a user tree */PtrHuffman createHuffmanTree (ElemType arr []) {PtrHuffman ptrArr [LENGTH]; PtrHuffman ptr, pRoot = NULL; for (int I = 0; I <LENGTH; I ++) {// initializes the struct pointer array, Each element in the array is a struct pointer type ptr = (PtrHuffman) malloc (sizeof (HuffmanTreeNode); ptr-> data = arr [I]; ptr-> left = ptr-> right = NULL; ptrArr [I] = ptr;} for (I = 1; I <LENGTH; I ++) {// create a Harman tree using n-1 cycles. // k1 indicates the subscript of the root node with the minimum weight in the forest. k2 indicates the minimum subscript int k1 =-1, k2; for (int j = 0; j <LENGTH; j ++) {if (ptrArr [j]! = NULL & k1 =-1) {k1 = j; continue;} if (ptrArr [j]! = NULL) {k2 = j; break ;}// assign the minimum value pointed to by the pointer in the pointer array to the index number k1, the next small value is assigned to for (j = k2; j <LENGTH; j ++) {if (ptrArr [j]! = NULL) {if (ptrArr [j]-> data <ptrArr [k1]-> data) {k2 = k1; k1 = j ;} else if (ptrArr [j]-> data <ptrArr [k2]-> data) {k2 = j ;}}} // create a new tree from the minimum and secondary least weights trees. The pRoot points to the root node pRoot = (PtrHuffman) malloc (sizeof (HuffmanTreeNode )); pRoot-> data = ptrArr [k1]-> data + ptrArr [k2]-> data; pRoot-> left = ptrArr [k1]; pRoot-> right = ptrArr [k2]; ptrArr [k1] = pRoot; // assign the pointer to the new tree to ptrArr pointer array, position 1, ptrArr [k2] = NULL; // The k2 position is null} return PRoot;}/*** calculate the length of the weighted path WPL */ElemType calculateWeightLength (PtrHuffman & ptrTree, int len) {if (ptrTree = NULL) {// The empty tree returns 0 return 0;} else {if (ptrTree-> left = NULL & ptrTree-> right = NULL) {// return ptrTree-> data * len;} else {return calculateWeightLength (ptrTree-> left, len + 1) + calculateWeightLength (ptrTree-> right, len + 1); // recursive downward calculation }}/ *** Harman tree encoding (the leaf node prints its encoding in ascending order) */void HuffmanCoding (PtrHuff Man & ptrTree, int len) {// static local variables are equivalent to global variables (only accessible in this function, but the lifecycle is similar to global variables) after the function exits, the variable is still present and initialized only at the first entry. The initialization statement will be skipped and the original value static int arr [20] will be retained; if (ptrTree! = NULL) {if (ptrTree-> left = NULL & ptrTree-> right = NULL) {printf ("encoding with node weight % d :", ptrTree-> data); for (int I = 0; I <len; I ++) {printf ("% d", arr [I]);} printf ("\ n");} else {arr [len] = 0; HuffmanCoding (ptrTree-> left, len + 1); arr [len] = 1; huffmanCoding (ptrTree-> right, len + 1) ;}}/ *** print the child node of each node in the Harman tree * if it is a leaf node, only the prompt * @ param node is displayed. The parent node of the child node */void printHuffmanTreeChildNode (PtrHuffman node) {if (no De-> left = NULL & node-> right = NULL) {printf ("x = % d is the leaf node in the Harman Tree", node-> data ); printf ("\ n"); return;} if (node-> left! = NULL) {printf ("x = % d", node-> data, node-> left-> data ); printf ("\ n");} if (node-> right! = NULL) {printf ("x = % d", node-> data, node-> right-> data ); printf ("\ n");} printf ("\ n");}/*** print the node of the Harman tree in the middle order */void midOrderprintHuffmanTreeNode (PtrHuffman & pRoot) {if (pRoot = NULL) {return;} else {midOrderprintHuffmanTreeNode (pRoot-> left); printf ("% d", pRoot-> data ); midOrderprintHuffmanTreeNode (pRoot-> right) ;}/ *** print the node of the Harman tree in sequence */void PreOrderprintHuffmanTreeNode (PtrHuffman & pRoot) {if (pRoot = NULL) {return;} else {printHuffmanTreeChildNode (pRoot); // print the child node PreOrderprintHuffmanTreeNode (pRoot-> left) of each node in the Harman tree in sequence ); preOrderprintHuffmanTreeNode (pRoot-> right) ;}/ *** test program entry */int main () {ElemType arr [] = {3, 9, 5, 12, 6, 15 }; ptrHuffman pRoot = createHuffmanTree (arr ); // return the pointer printf ("=========== print the data of the Harman node in the middle order "); midOrderprintHuffmanTreeNode (pRoot); printf ("\ n "); printf ("=========== print the Harman Tree node relationship in sequence =============\ n"); PreOrderprintHuffmanTreeNode (pRoot ); printf ("=========== calculate the length of the weighted path =============\ n "); printf ("WeightLength = % d \ n", calculateWeightLength (pRoot, 0); printf ("\ n "); printf ("============= the heap tree encoding of each node ===========\ n"); HuffmanCoding (pRoot, 0); fprintf (stdout, "\ n"); return 0 ;}
Running result: