数据结构伪C代码:6.树和二叉树

来源:互联网 发布:javascript文献书籍 编辑:程序博客网 时间:2024/05/16 19:00
//---------------二叉树的顺序链表表示----------------#define MAX_TREE_SIZE 100     //二叉树的最大结点数typedef TElemType SqBiTree[MAX_TREE_SIZE];   //0号单元存储根结点SqBiTree  bt;//---------------二叉树的二叉链表存储表示------------typedef struct BiTNode{  TElemType    data;  struct BiTNode  *lchild,*rchild;  //左右孩子指针}BiTNode,*BiTree;//算法6.1status PreOrderTraverse(BiTree T,status (*visit)(TElemType e)){//采用二叉链表存储结构,visit是对数据元素操作的应用函数//先序遍历二叉树T的递归算法,对每个数据元素调用函数visit//   status PrintElement(TElemType e){   //输出元素e的值//           printf(e);//           return ok;//    }     if(T){       if(visit(T->data))       if(PreOrderTraverse(T->lchild,visit))       if(PreOrderTraverse(T->rchild,visit))       return ok;       return error;     }     else     return ok;}//算法6.2status InOrderTraverse(BiTree T,status (*visit)(TElemType e)){//中序遍历二叉树T的非递归算法,对每个数据元素调用visit   InitStack(S);   Push(S,T);  //根指针进栈   while(!StackEmpty(S)){     while(!GetTop(S,p)&&p)  //向左走到尽头       Push(S,p->lchild);       Pop(S,p);   //空指针退栈     if(!StackEmpty(S)){        //访问结点,向右一步        Pop(S,p);        if(!visit(p->data))         return error;        Push(S,p->rchild);     }   }  return ok;}//算法6.3status InOrderTraverse(BiTree T,status (*visit)(TElemType e)){//中序遍历二叉树T的非递归算法,对每个数据元素调用visit   InitStack(S);   p=T;     while(p||!StackEmpty(S)){     if(p){  //根指针进栈,遍历左子树       Push(S,p);       p=p->lchild;     }     else{   //根指针退栈,访问根结点,遍历右子树       Pop(S,p);       if(!visit(p->data))       return error;       p=p->rchild;     }   }  return ok;}//算法6.4status CreateBiTree(BiTree &T){//按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树//构造二叉链表表示的二叉树T   scanf(&ch);    if(ch==' ')    T=NULL;    else{     if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))       exit (overflow);     T->data=ch;        //生成根节点     CreateBitTree(T->lchild); //构造左子树     CreateBitTree(T->rchild); //构造右子树    }    return ok;}//------------------二叉树的二叉线索存储表示------------------typedef enum PointerTag{Link,Thread};   //Link==0: 指针,Thread==1: 线索typedef struct {   TElemType data;   struct BiThrNode *lchild,*rchild;  //左右孩子指针   PointerTag LTag,RTag;              //左右标志}BiThrNode,*BiThrTree;//算法6.5status InOrderTraverse_Thr(BiThrTree T,status(*visit)(TElemType e)){//T指向头结点,头结点的左链lchild指向根结点,可参见线索化算法//中序遍历二叉树T的非递归算法,对每个数据元素调用visit     p=T->lchild;   //p指向根结点     while(p!=T){   //空树或遍历结束时,p==T        while(p->Ltag==Link)          p=p->lchild;        if(!visit(p->data))          return error;        while(p->Rtag==Thread&&p->rchild!=T){          p=p->rchild;          visit(p->data);        }        p=p->rchild;     }    return ok;}//算法6.6status InOrderThreading(BiThrTree &Thrt,BiThrTree T){//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点   if(!(Thrt=(BiThrTree)malloc(sizeof(BiThrNode))))     exit(overflow);   //建立头结点   Thrt->LTag=Link;       Thrt->RTag=Thread;   Thrt->rchild=Thrt;   //右指针回指   if(!T)   Thrt->lchild=Thrt;  //若二叉树为空,则左指针回指   else{   Thrt->lchild=T;   pre=Thrt;   InThreading(T);     //中序遍历进行中序线索化   //最后一个结点线索化   pre->rchild=Thrt;   pre->RTag=Thread;   //   Thrt->rchild=pre;   }   return ok;  }//算法6.7void InThreading(BiThrTree p){  if(p){   InThreading(p->lchild); //左子树线索化   if(!p->lchild){    //前驱线索    p->LTag=Thread;    p->lchild=pre;   }   if(!pre->rchild){    //后继线索    pre->RTag=Thread;    pre->rchild=p;   }   pre=p; //保持pre指向p的前驱  InThreading(p->rchild);  //右子树线索化  }}//---------------树的双亲表存储表示-------------------#define  MAX_TREE_SIZE   100typedef  struct PTNode{ //结点结构   TElemType    data;   int parent;    //双亲位置域}PTNode;typedef struct {    //树结构   PTNode   nodes[MAX_TREE_SIZE];   int      r,n;  //根的位置和结点数}PTree;//--------------树的孩子链表存储表示-------------------typedef struct CTNode{ //孩子结点   int child;   struct CTNode  *next;}*ChildPtr;typedef struct{  TElemType  data;  ChildPtr   firstchild; //孩子链表头指针}CTBox;typedef struct{  CTBox nodes[MAX_TREE_SIZE];  int n,r;      //结点数和根的位置}CTree;//------------树的二叉链表(孩子-兄弟)存储表示-----------typedef struct CSNode{   ElemType   data;   struct  CSNode  *firstchild,*nextsibling;}CSNode,*CSTree;//---------------ADT MFSet------------------------typedef PTree MFSet;//算法6.8int find_mfset(MFSet S,int i){//找集合S中i所在子集的根   if(i<1||i>S.n)    return -1;//i不属于S中任一子集   for(j=i;S.nodes[j].parent>0;j=S.nodes[j].parent);   return j;}//算法6.9status merge_mfset(MFSet &S,int i,int j){//S.nodes[i]和S.nodes[j]分别为S的互不相交的两个子集Si和Sj的根结点//求并集SiUSj   if(i<1||i>S.n||j<1||j>S.n)    return error;   S.nodes[i].parent=j;   return ok;}//算法6.10void mix_mfset(MFSet &S,int i,int j){//S.nodes[i]和S.nodes[j]分别为S的互不相交的两个子集Si和Sj的根结点//求并集SiUSjif(i<1||i>S.n||j<1||j>S.n) return error;if(S.nodes[i].parent>S.nodes[j].parent){  //Si所含成员数比Sj少  S.nodes[j].parent+=S.nodes[i].parent;  S.nodes[i].parent=j;}else{ S.nodes[i].parent+=S.nodes[j].parent; S.nodes[j].parent=i;}return ok;}//算法6.11int fix_mfset(MFSet &S,int i){//确定i所在子集,并将从i至根路径上所有结点都变成根的孩子结点  if(i<1||i>S.n)  return -1;  //i不是S中任一子集的成员  for(j=i;S.nodes[j].parent>0;j=S.nodes[j].parent);  for(k=i;k!=j;k=t){    t=S.nodes[k].parent;    S.nodes[k].parent=j;  }  return j;}//------------------赫夫曼树和赫夫曼编码的存储表示-----------------typedef struct{   unsigned int weight;   unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree;    //动态分配数组存储赫夫曼树typedef char **HuffmanCode; //动态分配数组存储赫夫曼编码表//算法6.12void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){//w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC   if(n<=1)   return;   m=2*n-1;   HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号单元未用   for(p=HT,i=1;i<=n;i++,p++,w++)     *p={*w,0,0,0};   for(;i<=m;i++,p++)     *p={0,0,0,0};   for(i=n+1;i<=n;i++){   //建赫夫曼树   //在HT[1...i-1]选择parent为0且weight最下的两个结点,其序号分别为s1和s2      Select(HT,i-1,s1,s2);      HT[s1].parent=i;      HT[s2].parent=i;      HT[i].lchild=s1;      HT[i].rchild=s2;      HT[i].weight=HT[s1].weight+HT[s2].weight;   }   //--------从叶子到根逆向求每个字符的赫夫曼编码--------------------    HC=(HuffmanCode)malloc((n+1)*sizeof(char *));//分配n个字符编码的头指针向量    cd=(char *)malloc(n*sizeof(char));           //分配求编码的工作空间    cd[n-1]="\n";                                //编码结束符    for(i=1;i<=n;i++){                           //逐个字符求赫夫曼编码    start=n-1;                                 //编码结束符位置      for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)  //从叶子到根逆向求编码        if(HT[f].lchild==c)        cd[--start]="0";        else        cd[--start]="1";      HC[i]=(char *)malloc((n-start)*sizeof(char));  //为第i个字符编码分配空间      strcpy(HC[i],&cd[start]);                  //从cd复制编码(串)到HC    }  free(cd);     //释放工作空间}//算法6.13//-----------------无栈非递归遍历赫夫曼树,求赫夫曼编码--------------HC=(HuffmanCode)malloc((n+1)*sizeof(char *));p=m;cdlen=0;for(i=1;i<=m;i++)  HT[i].weight=0;  //遍历赫夫曼树时用作结点状态标志  while(p){    if(HT[p].weight==0){   //向左      HT[p].weight=1;      if(HT[p].lchild!=0){        p=HT[p].lchild;        cd[cdlen++]="0";      }      else if(HT[p].rchild==0){//登记叶子结点的字符的编码        HC[p]=(char *)malloc((cdlen+1)*sizeof(char));        cd[cdlen]="\0";        strcpy(HC[p],cd);      }    }    else if(HT[p].weight==1){   //向右      HT[p].weight=2;      if(HT[p].rchild!=0){        p=HT[p].rchild;        cd[cdlen++]="1";      }      else{  //HT[p].weight==2,退回        HT[p].weight=0;        p=HT[p].parent;        cdlen--;   //退到父结点,编码长度减1      }    }  }//算法6.14void PowerSet(int i,int n){//求含n个元素的集合A的幂集(A);进入函数时已对A重前i-1个元素做了取舍处理//现从第i个元素起进行取舍处理。若i>n,则求得幂集的一个元素,并输出之。//初始调用:PowerSet(1,n);   if(i>n)    输出幂集的一个元素;   else{    取第i个元素;    PowerSet(i+1,n);    舍第i个元素;    PowerSet(i+1,n);   }}//算法6.15void GetPowerSet(int i,List A,List &B){//线性表A表示集合A,线性表B表示幂集(A)的一个元素//局部量k为进入函数时表B的当前长度;第一次调用本函数时,B为空表,i=1   if(i>ListLength(A))    Output(B);  //输出当前B值,即(A)的一个元素   else{    GetElem(A,i,x);    k=ListLength(B);    ListInsert(B,k+1,x);    GetPowerSet(i+1,A,B);    ListDelete(B,k+1,x);    GetPowerSet(i+1,A,B);   }}//算法6.16void Trial(int i,int n){//进入本函数时,在n*n棋盘前i-1行已放置了互不攻击的i-1个棋子//现从第i行起继续为后续棋子选择合适位置//当i>n时,求得一个合法布局,输出之  if(i>n)  输出棋盘的当前布局; //n为4时,即为4皇后问题  else   for(j=1;j<=n;j++){    在第i行第j列放置一个棋子;    if(当前布局合法)    Trial(i+1,n);    移走第i行第j列的棋子;  }}

0 0