树的更多相关算法-3

此代码包含了构建哈夫曼树的代码,在后面几段
 

  1.  
  2. //计算一个二叉树的节点个数,可以把所有的节点入队列,然后观察其rear的值,就知道其节点的个数,  这是一种广度的遍历方法 
  3. //下面的是一中深度的遍历的方法  当节点为NULL时候,返回0,  当节点无子节点时,返回1 , 否则得话返回左右节点的总数 
  4. int Nodes(BTNode *b) 
  5.     int num1 = 0, num2 = 0; 
  6.     if(b == NULL)  return 0; 
  7.     else if(b->lchild == NULL && b->rchild == NULL) return 1; 
  8.     else  
  9.     { 
  10.         num1 = Nodes(b->lchild);       //此处记录的是其左子树的所有子节点的数目 
  11.         num2 = Nodes(b->rchild);      // 此处记录的是右子树所有节点的数目 
  12.         return (num1 + num2 + 1);     //此处 返回其左子树的数目+右子树的数目+ 本身的数目(也就是那个1) 
  13.     } 
  14.  
  15. void LeafNodes(BTNode *b, int &leafnum)      //此函数记录叶子节点的数目, 与上面的函数类似,不过因为此函数不用计数 枝节点的数目, 所以没有num1 num2 等变量 
  16. {                                            // 当其找到一个叶子节点的时候,就把叶子节点的计数器 ++,   因为leafnum是 &传参, 所以不用担心 回代的问题 
  17.     if(b == NULL) return ; 
  18.     else if(b->lchild == NULL && b->rchild  == NULL)  ++leafnum; 
  19.     else 
  20.     { 
  21.         LeafNodes(b->lchild,leafnum); 
  22.         LeafNodes(b->rchild,leafnum); 
  23.     }    
  24.  
  25. int Nodes2(BTNode *b)              //此函数同样是求 树的叶子节点的数目 
  26.     int num1 = 0, num2 = 0; 
  27.     if(b == NULL)  return 0; 
  28.     else if(b->lchild == NULL && b->rchild == NULL) {  return 1;} 
  29.     else  
  30.     { 
  31.         num1 = Nodes2(b->lchild);    
  32.         num2 = Nodes2(b->rchild);    
  33.         return (num1 + num2 );      //此处不同的是 没有 + 1, 产生的递增效果就是  枝节点 不会被递增上, 也就是说只有叶子节点才可以 对其产生作用。。。  此处加1 产生的作用是非常大的(因为递增的原因) 
  34.     } 
  35.  
  36. void  DNodes(BTNode *b, int &dnum)       //此函数计算 有两个子节点的 节点的个数 
  37.     if(b != NULL)            //当节点不为空的时候进行操作 
  38.     { 
  39.         if(b->lchild != NULL && b->rchild != NULL)     //此处表示 遇到了有双子节点的 节点 
  40.             ++dnum;                      
  41.         DNodes(b->lchild,dnum);                       //遍历左子树 
  42.         DNodes(b->rchild,dnum);                      //遍历右子树  
  43.     } 
  44.  
  45. int DNodes2(BTNode *b)                      //此函数是求树中 有双子节点的节点的个数 
  46.     int num1 = 0, num2 = 0, n = 0; 
  47.     if(b == NULL) return 0; 
  48.     else if(b->lchild == NULL || b->rchild == NULL) n = 0;        //上面两个表明不符合条件 把 n置为 0  
  49.     else { n = 1; }      
  50.     num1 = DNodes2(b->lchild); 
  51.     num2 = DNodes2(b->rchild); 
  52.     return (num2 + num1 + n);                           //由题意知, n的值只能为 0 或 1 
  53.  
  54. void  DNodes3(BTNode *b, int &dnum)         //此函数也是求 一个树中有多少个 双节点 
  55.     int num1 = 0, num2 = 0; 
  56.     if(b != NULL)                          //当节点不为空的时候进行 
  57.     { 
  58.         if(b->rchild == NULL || b->lchild == NULL)   //当节点只有一个子节点的时候,进行递归操作 
  59.         { 
  60.             DNodes3(b->lchild, dnum); 
  61.             DNodes3(b->rchild, dnum); 
  62.         }else 
  63.         {  
  64.             ++dnum;                                  //当节点有两个子节点的时候, 把计数器++,  然后继续执行递归操作 
  65.             DNodes3(b->lchild, dnum); 
  66.             DNodes3(b->rchild, dnum); 
  67.         } 
  68.     } 
  69.  
  70.  
  71.  
  72. void  DelTree(BTNode *b)  //此函数用来释放 树中节点的所占用的空间,  释放只能采用后序遍历,不能使用先序或者中序遍历,因为中有将子树的空间释放掉后才能释放根节点的空间 
  73.     if(b !=  NULL) 
  74.     {   DelTree(b->lchild); 
  75.         DelTree(b->rchild);           
  76.         free(b); 
  77.     } 
  78.  
  79. void Swap(BTNode *&b)         //交换左右子树  用到的还是 后序 递归 
  80.     BTNode *temp; 
  81.     if(b != NULL)           //当节点存在的时候 进行操作 
  82.     { 
  83.         Swap(b->lchild); 
  84.         Swap(b->rchild); 
  85.         temp = b->lchild;           //交换左右子树 
  86.         b->lchild = b->rchild; 
  87.         b->rchild = temp; 
  88.     } 
  89.  
  90. //对树的递归操作  莫过于先 遍历左子树, 在遍历右子树, 这是一个方面。 另一个方面是 先序 中序 还是后序 
  91.  
  92. void Swap1(BTNode *b, BTNode *&b1)             //此函数是由一个树,重新构建得到其另外一个左右子树交换的树。 
  93.     if(b == NULL) 
  94.     { 
  95.         b1 = NULL; 
  96.     } 
  97.     else 
  98.     { 
  99.         b1 = (BTNode *)malloc(sizeof(BTNode)); 
  100.         b1->data = b->data; 
  101.         Swap1(b->lchild, b1->rchild); 
  102.         Swap1(b->rchild, b1->lchild); 
  103.     } 
  104.  
  105. void ancestor(BTNode *b,char r, char s)   //此函数是求得 值为 r s 节点的最近的祖先节点 
  106. {                                       //不是一般性本例子采用后序遍历树, 并且假设 r 节点在 s 节点的左边 
  107.     BTNode *st[MAXSIZE],  *temp, *temp2; //本函数的思路是,后序遍历树 把遇到的节点进栈(这时候入栈中的元素都是r的祖先节点),当先(因为规定r节点在s节点的左边)遇到值为r节点的时候,就把栈的所有节点的值放入path数组,用以记录访问过的值 
  108.     int top = -1;                       //当遇到值为s的节点时候,就比较path数组与栈中的节点值,直到第一个不同即为其共同的祖先节点(当出栈的时候把 其不是公共的节点给出去了) 
  109.     bool  flag = true
  110.     char path[MAXSIZE]; 
  111.      
  112.     if(b != NULL)        
  113.     { 
  114.         temp = b; 
  115.         do      //此循环是后序遍历 
  116.         {        
  117.             while(temp != NULL)        //把左子树递归进栈 
  118.             { 
  119.                 ++top; 
  120.                 st[top] = temp; 
  121.                 temp = temp->lchild; 
  122.             } 
  123.             flag = true;  
  124.             temp2 = NULL; 
  125.             while(flag && top > -1)  
  126.             { 
  127.                 temp = st[top]; 
  128.                 if(temp->rchild == temp2)         //当节点的右节点访问过 或者 其右节点为空的时候,就访问它 
  129.                 {                    
  130.                     if(temp->data == r)         //判断节点的值是否为r 如果是就给path数组赋值 
  131.                     { 
  132.                         for(int loop1=0; loop1 <= top; ++loop1) 
  133.                             path[loop1] = st[loop1]->data; 
  134.                         --top;                       //执行出栈操作 
  135.                         temp2 = temp;               //表示已经访问过,,即对其做标记 
  136.                     }else if(temp->data == s) 
  137.                     { 
  138.                         int loop2 = 0; 
  139.                         while(st[loop2]->data == path[loop2]) 
  140.                             ++loop2; 
  141.                         cout<<r<<" 与 "<<s<<" , 最近的共同祖先是 :"<<path[--loop2]<<endl; 
  142.                         return ; 
  143.                     }else 
  144.                     { 
  145.                         --top; 
  146.                         temp2 = temp; 
  147.                     } 
  148.                 }else 
  149.                 { 
  150.                     flag = false;                 //此语句块表示当其右子节点没有被访问的时候,就跳出循环用flag做标志变量, 然后对其右子树执行递归操作 
  151.                     temp = temp->rchild; 
  152.                 } 
  153.             } 
  154.         }while(top > -1); 
  155.     } 
  156. char path1[MAXSIZE]; 
  157. int top = -1; 
  158. void AncestorPath(BTNode *b, char s)     //此函数实现的是输出根节点到 值为 s 节点之间的路径,采用的递归操作 
  159. {                                       //这是一种先序遍历 
  160.     if(b != NULL) 
  161.     { 
  162.         ++top; 
  163.         path1[top] = b->data;      //入栈 
  164.         if(b->data == s)           //判断是否满足条件 
  165.         {  
  166.             cout<<"路径为:"<<endl; 
  167.             for(int loop1 = 0; loop1 <= top; ++loop1) 
  168.                 cout<<path1[loop1]<<' '
  169.             cout<<endl; 
  170.             return
  171.         } 
  172.         AncestorPath(b->lchild,s); 
  173.         AncestorPath(b->rchild,s); 
  174.         --top;                 //恢复环境 
  175.     } 
  176. //此上下两个函数 先序 与 后序的区别是 先序是先判断是否满足条件在进行 遍历左子树,  后序则是先深度遍历左子树,在判断右子树的时候,才判断是否满足条件 
  177. //不管怎么说都 在栈中存在的元素都是所求的元素的  祖先节点 
  178. void AncestorPath2(BTNode *b, char s)    //此函数同样是实现 根节点到值为s的节点之间路径输出,采用的方法是后序法,与求两个 节点 最近的祖先节点方法类似 
  179.     BTNode *st[MAXSIZE], *temp, *temp2; 
  180.     int top = -1; 
  181.     bool flag = true
  182.     char path[MAXSIZE]; 
  183.  
  184.     if(b != NULL) 
  185.     { 
  186.         temp = b; 
  187.         do 
  188.         { 
  189.             while(temp != NULL) 
  190.             { 
  191.                 ++top; 
  192.                 st[top] = temp; 
  193.                 temp = temp->lchild; 
  194.             } 
  195.             temp2 = NULL; 
  196.             flag = true
  197.             while(flag && top > -1) 
  198.             { 
  199.                 temp = st[top]; 
  200.                 if(temp->rchild == temp2) 
  201.                 { 
  202.                     if(temp->data == s) 
  203.                     { 
  204.                         cout<<"根节点到 "<<s<<" 之间的路径为 :"<<endl; 
  205.                         for(int loop1 = 0; loop1 <= top; ++loop1) 
  206.                             cout<<st[loop1]->data<<' '
  207.                         cout<<endl; 
  208.                         return
  209.                     } 
  210.                     --top; 
  211.                     temp2 = temp; 
  212.                 }else 
  213.                 { 
  214.                     flag = false
  215.                     temp = temp->rchild; 
  216.                 } 
  217.             } 
  218.  
  219.         }while(top > -1); 
  220.     } 
  221. char path3[MAXSIZE]; 
  222. int top2 = -1; 
  223. void Link(BTNode *b)          //先序找树中的叶子节点 
  224.     if(b != NULL) 
  225.     { 
  226.         if(b->lchild == NULL && b->rchild == NULL) 
  227.             path3[++top2] = b->data; 
  228.         else 
  229.         { 
  230.             Link(b->lchild); 
  231.             Link(b->rchild); 
  232.         } 
  233.     } 
  234.  
  235. void Link2(BTNode *b)          //采用中序遍历 找叶子节点 
  236.     if(b != NULL) 
  237.     { 
  238.         Link2(b->lchild); 
  239.         if(b->lchild == NULL && b->rchild == NULL) 
  240.             path3[++top2] = b->data; 
  241.         Link2(b->rchild); 
  242.     } 
  243.  
  244. void Print(BTNode *b,int w)             //把树向 逆时针旋转90度打印出来 
  245.     if(b != NULL) 
  246.     { 
  247.         Print(b->rchild, w+5); 
  248.         for(int loop1 = 0; loop1 <= w; ++loop1) 
  249.             cout<<' '
  250.         cout<<b->data<<endl; 
  251.         Print(b->lchild,w+5); 
  252.     } 
  253.  
  254. float ExpValue(BTNode *b)      //此函数是计算一个树组成的表达式 
  255.     if(b != NULL)              //当其不为0的时候执行操作 
  256.     {        
  257.         switch(b->data) 
  258.         { 
  259.         case '+' : 
  260.             return ExpValue(b->lchild) + ExpValue(b->rchild);  break
  261.         case '-' : 
  262.             return ExpValue(b->lchild) - ExpValue(b->rchild);  break
  263.         case '*' : 
  264.             return ExpValue(b->lchild) * ExpValue(b->rchild);  break
  265.         case '/' : 
  266.             return ExpValue(b->lchild) / ExpValue(b->rchild);  break
  267.         default : 
  268.             return b->data - '0';           //此处目前只能是各位数,如果节点的值是数的话,就直接返回 
  269.         } 
  270.     } 
  271.  
  272. bool bflag = false;          //左子树的标记 
  273. bool bflag2 = false;        //右子树的标记 
  274. void  InorderExp(BTNode *b)       //此函数是通过树求得其表达式, 思路是当节点的数据域是符号的时候,就把其与左节点的数据域比较,如果左节点的数据域是符号并且 
  275. {                               //子节点的优先级比根节点的小,那么就输出‘(’并把标记设置为true,      当遍历右子树的时候仍然拿其与右子树的数据域比较如果,其符号的优先级比右子树的优先级大, 
  276.     if(b != NULL)               //就输出一个‘(’然后设置标记为true 
  277.     { 
  278.          
  279.         switch(b->data) 
  280.         { 
  281.         case '+' : 
  282.         case '-' : 
  283.             InorderExp(b->lchild);        //表示先遍历左子树 
  284.             cout<<b->data<<' ';         //输出其值 
  285.             InorderExp(b->rchild); break;  //遍历右子树 
  286.         case '*' : 
  287.         case '/' :               //当遇到 * /的时候就应当判断优先级了 
  288.             if(b->lchild != NULL)       //此处是判断左子树 
  289.             { 
  290.                 if(b->lchild->data == '+' || b->lchild->data == '-'
  291.                 {   cout<<'('
  292.                     bflag = true
  293.                 } 
  294.             } 
  295.  
  296.             InorderExp(b->lchild); 
  297.              
  298.             if(bflag) 
  299.             { cout<<')';  bflag = false;} 
  300.          
  301.             cout<<b->data<<' ';         //此处才是输出 * 或者/ 的地方,也就是在 ‘(’‘)’都输出完成的时候,如果有的话 
  302.              
  303.             if(b->rchild != NULL)       //此处判断右子树 
  304.             { 
  305.                 if(b->rchild->data == '+' || b->rchild->data == '-'
  306.                 {   cout<<'(';               
  307.                     bflag2 = true
  308.                 } 
  309.             } 
  310.             InorderExp(b->rchild); 
  311.              
  312.             if(bflag2) 
  313.             { cout<<')'; bflag2 = false; } 
  314.             break
  315.         default : 
  316.             cout<<b->data<<' '
  317.             break
  318.         } 
  319.     }    
  320.  
  321. int process(char op1, char op2) //此函数是判断优先级 
  322.     if(op1 != '+' && op1 != '-' && op1 != '*' && op1 != '/')  return -1;  
  323.     if(op2 != '+' && op2 != '-' && op2 != '*' && op2 != '/')  return -1; 
  324.  
  325.     if(op1 == '+' || op1 == '-'
  326.     { 
  327.         return 0; 
  328.     } 
  329.     if(op1 == '*' || op1 == '/'
  330.     { 
  331.         if(op2 == '+' || op2 == '-'
  332.             return 1; 
  333.     } 
  334.  
  335. void InorderExp2(BTNode *b)    //此函数也是求得表达式 
  336.     int flag1 = 2; 
  337.     int flag2 = 2; 
  338.     if(b != NULL) 
  339.     { 
  340.         if(b->lchild != NULL) 
  341.         { 
  342.             flag = process(b->data,b->lchild->data); 
  343.             if(flag == 1) cout<<'('
  344.             InorderExp(b->lchild); 
  345.             if(flag == 1) cout<<')'
  346.         } 
  347.         cout<<b->data; 
  348.         if(b->rchild != NULL) 
  349.         { 
  350.             flag2 = process(b->data,b->rchild->data); 
  351.             if(flag2 == 1) cout<<'('
  352.             InorderExp(b->rchild); 
  353.             if(flag2 == 1) cout<<')'
  354.         } 
  355.     } 
  356.  
  357. float value[MAXSIZE]; 
  358.  
  359. int top22 = -1; 
  360. char postExp[MAXSIZE]; 
  361. void PostExp(BTNode *b)   //此函数的目的是把树转换为后缀表达式,怎么转换为后缀表达式呢??? 采用后序遍历即可 
  362. {                       //因为符号位总是位于双亲结点,这样就能先把 数字位给进栈, 然后进栈符号位 
  363.     if(b != NULL) 
  364.     { 
  365.         PostExp(b->lchild); 
  366.         PostExp(b->rchild); 
  367.         ++top22; 
  368.         postExp[top22] = b->data; 
  369.     } 
  370.  
  371. void CompValue(char postExp[]) //此函数是为了通过后缀表达式来求得其值 
  372. {   top = -1; 
  373.     char ch; 
  374.     int loop1 = 0; 
  375.     ch = postExp[loop1]; 
  376.     float lValue = 0.0f, rValue = 0.0f, fValue = 0.0f; 
  377.     while(ch != '\0'
  378.     { 
  379.         switch(ch) 
  380.         { 
  381.         case '+' : 
  382.             rValue = value[top]; 
  383.             --top; 
  384.             lValue = value[top]; 
  385.             fValue = lValue + rValue; 
  386.             value[top] = fValue; 
  387.             ch = postExp[++loop1]; 
  388.             break
  389.         case '-' : 
  390.             rValue = value[top]; 
  391.             --top; 
  392.             lValue = value[top]; 
  393.             fValue = lValue - rValue; 
  394.             value[top] = fValue; 
  395.             ch = postExp[++loop1]; 
  396.             break
  397.         case '*' : 
  398.             rValue = value[top]; 
  399.             --top; 
  400.             lValue = value[top]; 
  401.             fValue = lValue * rValue; 
  402.             value[top] = fValue; 
  403.             ch = postExp[++loop1]; 
  404.             break
  405.         case '/' : 
  406.             rValue = value[top]; 
  407.             --top; 
  408.             lValue = value[top]; 
  409.             if(rValue == 0)  { cout<<"发生除零错误。"<<endl; exit(1); }  
  410.             fValue = lValue / rValue; 
  411.             value[top] = fValue; 
  412.             ch = postExp[++loop1]; 
  413.             break
  414.         default : 
  415.             fValue = float( ch - '0');     //因为数字位 是个位数,所以此处没有进行处理 
  416.             ++top; 
  417.             value[top] = fValue; 
  418.             ch = postExp[++loop1]; 
  419.             break
  420.         } 
  421.     } 
  422.     if(top == 0) 
  423.     { cout<<"所求的值为:"<<value[top]<<endl; } 
  424.     else 
  425.     { cout<<"求值错误。"<<endl; } 
  426.  
  427. void NodeToRoot(BTNode *b)    //此函数是在结点中增加一个双亲域以后, 输出每个结点到根节点的路径 
  428. {                           //采用先序遍历 
  429.     BTNode *temp; 
  430.     if(b != NULL) 
  431.     { 
  432.         temp = b; 
  433.         while(temp != NULL) 
  434.         { 
  435.             cout<<temp->data<<' '
  436.             temp = temp->parent; 
  437.         } 
  438.         cout<<endl; 
  439.         NodeToRoot(b->lchild); 
  440.         NodeToRoot(b->rchild); 
  441.     } 
  442.  
  443. void PreToPost(ElemType pre[], int begin1, int end1, ElemType post[], int begin2, int end2) 
  444. {                               //此函数将先序序列转换为后序序列, 因为先序序列的第一个元素是后序序列的最后一个元素,  然后就以此为条件进行递归操作 
  445.     int half = 0;  
  446.     if(end1 >= begin1) 
  447.     {   half = (end1 - begin1 ) / 2;       //half保存了中间的值 
  448.         post[end2] = pre[begin1];      
  449.         PreToPost(pre, begin1 + 1, begin1 + half, post, begin2,begin2 + half -1); //此处是遍历先序左子树, 要注意的是在使用half的时候,应该加上开始点,  其half是一个区间,不是一个点,加上begin开始点后,才表示中间点的位置 
  450.         PreToPost(pre, begin1 + half + 1, end1, post,begin2 + half, end2 -1);     //此处是遍历先序右子树 
  451.     }   
  452.  
  453. void CreateHT(HTNode ht[], int n)    //通过数组构造一棵哈夫曼树, 因为一棵哈夫曼树有n个节点的话,就会有总共2n - 1 个节点 
  454.     int loop1 = 0, loop2 = 0, loop3 = 0, lpos = 0, rpos = 0; 
  455.     float weight1 = 0.0f, weight2 = 0.0f;      //用来保存权值,其中weight1 保存的是较小的 
  456.  
  457.     for(loop1 =0; loop1 < n; ++loop1)    //此循环把双亲 左右孩子节点域置为 -1; 
  458.     {   ht[loop1].parent = -1; 
  459.         ht[loop1].lchild = -1; 
  460.         ht[loop1].rchild = -1; 
  461.     } 
  462.  
  463.     for(loop1 = n; loop1 < 2 * n + 1; ++loop1)     //由于数组前面的n个节点是叶子节点,所以此处处理 后面的 n -1 个非叶子节点 
  464.     { 
  465.         weight1 = 32767.0f; 
  466.         weight2 = 32767.0f; 
  467.  
  468.         for(loop2 = 0; loop2 < loop1; ++loop2 ) 
  469.         { 
  470.             if(ht[loop2].parent == -1)         //只处理没有双亲节点的 节点 
  471.             { 
  472.                 if(ht[loop2].weight < weight1)      //保存最小的和 第二最小的权值及其位置 
  473.                 { 
  474.                     weight2 = weight1;     rpos = lpos; 
  475.                     weight1 = ht[loop2].weight;  lpos = loop2; 
  476.                 } 
  477.                 else if(ht[loop2].weight < weight2) 
  478.                 { 
  479.                     weight2 = ht[loop2].weight; 
  480.                     rpos = loop2; 
  481.                 } 
  482.             } 
  483.         } 
  484.         ht[loop1].lchild = lpos;    ht[loop1].rchild = rpos;  ht[loop1].weight = ht[lpos].weight + ht[rpos].weight; 
  485.         ht[lpos].parent = loop1;    ht[rpos].parent = loop1; 
  486.     } 
  487. //哈夫曼编码只能是叶子节点,并且哈夫曼树中只有度为 0 或2 的节点 
  488. typedef struct 
  489.     char cd[MAXSIZE]; //存储根节点到叶子节点的编码,即 0 或 1 
  490.     int start;        //开始位置 
  491. }HCode;   //存储哈夫曼遍历的 节点结构 
  492. /* 
  493. void CreateHCode(HTNode ht[], HCode hcd[], int n)    //此函数是根据哈夫曼树构造哈夫曼编码,思路是从每个叶子节点开始遍历到根节点, 如果节点是左节点 则表示为0 ,如果右节点否则表示为1  
  494. { 
  495.     int loop1 = 0, parent; 
  496.     HCode hc; 
  497.     for(loop1 = 0; loop1 < n; ++loop1)     //ht数组的前面n个元素是叶子节点, 所以遍历前面n个节点 
  498.     { 
  499.         hc.start = n; 
  500.         parent = ht[loop1].parent; 
  501.  
  502.         while(parent != -1)             //直到根节点 构造哈夫曼遍历 
  503.         { 
  504.             if(ht[parent].lchild == ht[loop1])      //如果是左节点的话,为 0 
  505.                 hc.cd[hc.start--] = '0'; 
  506.             else 
  507.                 hc.cd[hc.start--] = '1';           //否则为右节点,那么就为 1  
  508.             parent = ht[parent].parent;         // 
  509.  
  510.         } 
  511.         ++hc.start; 
  512.         hcd[loop1] = hc; 
  513.     } 
  514. } 
  515. */ 
  516. typedef char ElemType; 
  517. typedef struct hnode 
  518.     int weight; 
  519.     ElemType data; 
  520.     struct hnode *lchild, *rchild; 
  521. }HTree; 
  522.  
  523. typedef struct  
  524.     ElemType data; 
  525.     int weight; 
  526. }Node; 
  527. typedef struct  
  528.     char code[10]; 
  529.     int weight; 
  530.     ElemType data; 
  531. }NodeCode; 
  532.  
  533. struct cmp1 
  534.     bool operator() (HTree *node1, HTree *node2) 
  535.     { 
  536.         return node1->weight >= node2->weight; 
  537.     } 
  538. }; 
  539.  
  540. void CreateHuffm(HTree *&root, Node nodes[], int num) //此函数借助priority_queue<> 构造哈夫曼树 
  541.     int loop1 = 0, weight = 0; 
  542.     HTree *temp = NULL,*lchild = NULL, *rchild = NULL; 
  543.     priority_queue<HTree *, vector<HTree *>, cmp1>  qp; 
  544.  
  545.     for(loop1 = 0; loop1 < num; ++loop1) 
  546.     { 
  547.         temp = (HTree *)malloc(sizeof(HTree)); 
  548.         temp->lchild = temp->rchild = NULL; 
  549.         temp->data = nodes[loop1].data; 
  550.         temp->weight = nodes[loop1].weight; 
  551.         qp.push(temp); 
  552.     } 
  553.     while(qp.size() != 1) 
  554.     { 
  555.         lchild = qp.top(); 
  556.         qp.pop(); 
  557.         rchild = qp.top(); 
  558.         qp.pop(); 
  559.          
  560.         temp = (HTree *)malloc(sizeof(HTree)); 
  561.         temp->lchild = lchild; 
  562.         temp->rchild = rchild; 
  563.         temp->weight = lchild->weight + rchild->weight; 
  564.          
  565.         qp.push(temp);       
  566.     } 
  567.     root = qp.top(); 
  568.     qp.pop();    
  569.  
  570. void disp(HTree *tree) 
  571.     if(tree != NULL) 
  572.     { 
  573.         cout<<tree->weight<<endl; 
  574.         disp(tree->lchild); 
  575.         disp(tree->rchild); 
  576.     } 
  577.  
  578.  
  579. NodeCode code[MAXSIZE]; 
  580. int loop = 0, looop = 0; 
  581. char pathx[10]; 
  582.  
  583. void HuffmCode(HTree *tree)      //此函数求得每个节点的哈弗曼编码, 利用先序递归的方式 
  584.     if(tree != NULL) 
  585.     { 
  586.         if(tree->lchild == NULL && tree->rchild == NULL) 
  587.         { 
  588.             code[looop].data = tree->data; 
  589.             code[looop].weight = tree->weight; 
  590.             strcpy(code[looop].code, pathx);            //此步骤没用到loop的值,所以下面 
  591.             ++looop; 
  592.         } 
  593.         if(tree->lchild != NULL) 
  594.         { 
  595.             pathx[loop] = '0'
  596.             ++loop; 
  597.             pathx[loop] = '\0';                 //                                     应该加上'\0' 
  598.             HuffmCode(tree->lchild); 
  599.         } 
  600.         if(tree->rchild != NULL) 
  601.         { 
  602.             pathx[loop] = '1'
  603.             ++loop; 
  604.             pathx[loop] = '\0'
  605.             HuffmCode(tree->rchild); 
  606.         } 
  607.         --loop; 
  608.         pathx[loop] = '\0'
  609.     } 

 

你可能感兴趣的:(算法,树,哈夫曼树)