1. 引言
链 表结构上了。这样有利于对结点进行操作。
一棵树无论有多少叉,它最多有一个长子和一个排序恰在其下的兄弟。根据这样的定义,则每个结点的结构就都统一到了二叉
2. 树的二叉链表(孩子-兄弟)存储
#include "ds.h" typedef char TElemType; TElemType Nil=' '; // 以空格符为空 typedef struct CSNode { TElemType data; CSNode *firstchild, *nextsibling; }CSNode, *CSTree; #define ClearTree DestroyTree // 二者操作相同 typedef CSTree QElemType; typedef struct QNode{ QElemType data; struct QNode *next; }*QueuePtr; struct LinkQueue{ QueuePtr front, rear; }; void InitQueue(LinkQueue &Q); void DestroyQueue(LinkQueue &Q); void ClearQueue(LinkQueue &Q); Status QueueEmpty(LinkQueue Q); void EnQueue(LinkQueue &Q, QElemType e); Status DeQueue(LinkQueue &Q, QElemType &e); // 带头结点的单链队列 void InitQueue(LinkQueue &Q) { Q.front = (QueuePtr)malloc(sizeof(QNode)); if (!Q.front) exit(OVERFLOW); Q.front->next = NULL; Q.rear = Q.front; } void DestroyQueue(LinkQueue &Q) { QueuePtr q, p = Q.front; while (p) { q = p->next; free(p); p = q; } Q.front = Q.rear = NULL; } void ClearQueue(LinkQueue &Q) { QueuePtr q, p = Q.front->next; while (p) { q = p->next; free(p); p = q; } Q.front->next = NULL; Q.rear = Q.front; } Status QueueEmpty(LinkQueue Q) { if (Q.front == Q.rear) return TRUE; else return FALSE; } void EnQueue(LinkQueue &Q, QElemType e) { QueuePtr p = (QueuePtr)malloc(sizeof(QNode)); if (!p) exit(OVERFLOW); p->next = NULL; memcpy(&(p->data), &e, sizeof(QElemType)); Q.rear->next = p; Q.rear = p; } Status DeQueue(LinkQueue &Q, QElemType &e) { QueuePtr p = Q.front, q; if (Q.front == Q.rear) return FALSE; q = p->next; memcpy(&e, &(q->data), sizeof(QElemType)); p->next = q->next; if (Q.rear == q) Q.rear = Q.front; free(q); return OK; } // 先根遍历孩子—兄弟二叉链表结构的树T void PreOrderTraverse(CSTree T, void(*Visit)(TElemType)) { if (T) { Visit(T->data); // 先访问根结点 PreOrderTraverse(T->firstchild, Visit); // 再先根遍历长子子树 PreOrderTraverse(T->nextsibling, Visit); // 最后先根遍历下一个兄弟子树 } } void InitTree(CSTree &T) { T = NULL; } void DestroyTree(CSTree &T) { if (T) { if (T->firstchild) DestroyTree(T->firstchild); if (T->nextsibling) DestroyTree(T->nextsibling); free(T); T = NULL; } } void CreateTree(CSTree &T) { char c[20]; CSTree p, p1; LinkQueue q; int i, l; InitQueue(q); printf("请输入根结点(字符型,空格为空): "); scanf("%c%*c", &c[0]); if (c[0] != Nil) // 非空树 { T = (CSTree)malloc(sizeof(CSNode)); // 建立根结点 T->data = c[0]; T->nextsibling = NULL; EnQueue(q, T); // 入队根结点的指针 while (!QueueEmpty(q)) // 队不空 { DeQueue(q, p); // 出队一个结点的指针 printf("请按长幼顺序输入结点%c的所有孩子: ",p->data); gets(c); l = strlen(c); if (l > 0) // 有孩子 { p1 = p->firstchild = (CSTree)malloc(sizeof(CSNode)); // 建立长子结点 p1->data = c[0]; for (i = 1; i < l; i++) { p1->nextsibling = (CSTree)malloc(sizeof(CSNode)); // 建立下一个兄弟结点 EnQueue(q, p1); // 入队上一个结点 p1 = p1->nextsibling; p1->data = c[i]; } p1->nextsibling = NULL; EnQueue(q, p1); // 入队最后一个结点 } else p->firstchild = NULL; // 长子指针为空 } } else T = NULL; // 空树 } // 初始条件:树T存在。操作结果:若T为空树,则返回TURE,否则返回FALSE Status TreeEmpty(CSTree T) { if(T) // T不空 return FALSE; else return TRUE; } // 初始条件:树T存在。操作结果:返回T的深度 int TreeDepth(CSTree T) { CSTree p; int depth, max = 0; if (!T) // 树空 return 0; if (!T->firstchild) // 树无长子 return 1; for (p = T->firstchild; p; p = p->nextsibling) { // 求子树深度的最大值 depth = TreeDepth(p); if (depth > max) max = depth; } return max + 1; // 树的深度=子树深度最大值+1 } // 返回p所指结点的值 TElemType Value(CSTree p) { return p->data; } // 初始条件:树T存在。操作结果:返回T的根 TElemType Root(CSTree T) { if(T) return Value(T); else return Nil; } // 返回二叉链表(孩子—兄弟)树T中指向元素值为s的结点的指针。另加 CSTree Point(CSTree T,TElemType s) { LinkQueue q; QElemType a; if(T) // 非空树 { InitQueue(q); // 初始化队列 EnQueue(q,T); // 根结点入队 while(!QueueEmpty(q)) // 队不空 { DeQueue(q,a); // 出队,队列元素赋给a if(a->data==s) return a; if(a->firstchild) // 有长子 EnQueue(q,a->firstchild); // 入队长子 if(a->nextsibling) // 有下一个兄弟 EnQueue(q,a->nextsibling); // 入队下一个兄弟 } } return NULL; } // 初始条件:树T存在,cur_e是树T中结点的值。操作结果:改cur_e为value Status Assign(CSTree &T,TElemType cur_e,TElemType value) { CSTree p; if (T) // 非空树 { p = Point(T, cur_e); // p为cur_e的指针 if (p) // 找到cur_e { p->data = value; // 赋新值 return OK; } } return ERROR; // 树空或没找到 } // 初始条件:树T存在,cur_e是T中某个结点 // 操作结果:若cur_e是T的非根结点,则返回它的双亲,否则函数值为"空" TElemType Parent(CSTree T,TElemType cur_e) { CSTree p,t; LinkQueue q; InitQueue(q); if(T) // 树非空 { if (Value(T) == cur_e) // 根结点值为cur_e return Nil; EnQueue(q, T); // 根结点入队 while(!QueueEmpty(q)) { DeQueue(q,p); if(p->firstchild) // p有长子 { if(p->firstchild->data==cur_e) // 长子为cur_e return Value(p); // 返回双亲 t=p; // 双亲指针赋给t p=p->firstchild; // p指向长子 EnQueue(q,p); // 入队长子 while(p->nextsibling) // 有下一个兄弟 { p=p->nextsibling; // p指向下一个兄弟 if(Value(p)==cur_e) // 下一个兄弟为cur_e return Value(t); // 返回双亲 EnQueue(q,p); // 入队下一个兄弟 } } } } return Nil; // 树空或没找到cur_e } // 初始条件:树T存在,cur_e是T中某个结点 // 操作结果:若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回"空" TElemType LeftChild(CSTree T,TElemType cur_e) { CSTree f; f = Point(T,cur_e); // f指向结点cur_e if(f && f->firstchild) // 找到结点cur_e且结点cur_e有长子 return f->firstchild->data; else return Nil; } // 初始条件:树T存在,cur_e是T中某个结点 // 操作结果:若cur_e有右兄弟,则返回它的右兄弟,否则返回"空" TElemType RightSibling(CSTree T,TElemType cur_e) { CSTree f; f = Point(T,cur_e); // f指向结点cur_e if(f && f->nextsibling) // 找到结点cur_e且结点cur_e有右兄弟 return f->nextsibling->data; else return Nil; // 树空 } // 初始条件:树T存在,p指向T中某个结点,1≤i≤p所指结点的度+1,非空树c与T不相交 // 操作结果:插入c为T中p结点的第i棵子树 // 因为p所指结点的地址不会改变,故p不需是引用类型 Status InsertChild(CSTree &T,CSTree p,int i,CSTree c) { int j; if(T) // T不空 { if(i==1) // 插入c为p的长子 { c->nextsibling=p->firstchild; // p的原长子现是c的下一个兄弟(c本无兄弟) p->firstchild=c; } else // 找插入点 { p=p->firstchild; // 指向p的长子 j=2; while(p&&j<i) { p=p->nextsibling; j++; } if(j==i) // 找到插入位置 { c->nextsibling=p->nextsibling; p->nextsibling=c; } else // p原有孩子数小于i-1 return ERROR; } return OK; } else // T空 return ERROR; } // 初始条件:树T存在,p指向T中某个结点,1≤i≤p所指结点的度 // 操作结果:删除T中p所指结点的第i棵子树 // 因为p所指结点的地址不会改变,故p不需是引用类型 Status DeleteChild(CSTree &T,CSTree p,int i) { CSTree b; int j; if(T) // T不空 { if(i==1) // 删除长子 { b=p->firstchild; p->firstchild=b->nextsibling; // p的原次子现是长子 b->nextsibling=NULL; DestroyTree(b); } else // 删除非长子 { p=p->firstchild; // p指向长子 j=2; while(p&&j<i) { p=p->nextsibling; j++; } if(j==i) // 找到第i棵子树 { b=p->nextsibling; p->nextsibling=b->nextsibling; b->nextsibling=NULL; DestroyTree(b); } else // p原有孩子数小于i return ERROR; } return OK; } else return ERROR; } // 后根遍历孩子—兄弟二叉链表结构的树T void PostOrderTraverse(CSTree T,void(*Visit)(TElemType)) { CSTree p; if(T) { if(T->firstchild) // 有长子 { PostOrderTraverse(T->firstchild,Visit); // 后根遍历长子子树 p=T->firstchild->nextsibling; // p指向长子的下一个兄弟 while(p) { PostOrderTraverse(p,Visit); // 后根遍历下一个兄弟子树 p=p->nextsibling; // p指向再下一个兄弟 } } Visit(Value(T)); // 最后访问根结点 } } // 层序遍历孩子—兄弟二叉链表结构的树T void LevelOrderTraverse(CSTree T,void(*Visit)(TElemType)) { CSTree p; LinkQueue q; InitQueue(q); if(T) { Visit(Value(T)); // 先访问根结点 EnQueue(q,T); // 入队根结点的指针 while(!QueueEmpty(q)) // 队不空 { DeQueue(q,p); // 出队一个结点的指针 if(p->firstchild) // 有长子 { p=p->firstchild; Visit(Value(p)); // 访问长子结点 EnQueue(q,p); // 入队长子结点的指针 while(p->nextsibling) // 有下一个兄弟 { p=p->nextsibling; Visit(Value(p)); // 访问下一个兄弟 EnQueue(q,p); // 入队兄弟结点的指针 } } } } } void vi(TElemType c) { printf("%c ",c); } int main() { int i; CSTree T,p,q; TElemType e,e1; InitTree(T); printf("构造空树后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n",TreeEmpty(T),Root(T),TreeDepth(T)); CreateTree(T); printf("构造树T后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n",TreeEmpty(T),Root(T),TreeDepth(T)); printf("先根遍历树T:\n"); PreOrderTraverse(T,vi); printf("\n请输入待修改的结点的值 新值: "); scanf("%c%*c%c%*c",&e,&e1); Assign(T,e,e1); printf("后根遍历修改后的树T:\n"); PostOrderTraverse(T,vi); printf("\n%c的双亲是%c,长子是%c,下一个兄弟是%c\n",e1,Parent(T,e1),LeftChild(T,e1),RightSibling(T,e1)); printf("建立树p:\n"); InitTree(p); CreateTree(p); printf("层序遍历树p:\n"); LevelOrderTraverse(p,vi); printf("\n将树p插到树T中,请输入T中p的双亲结点 子树序号: "); scanf("%c%d%*c",&e,&i); q=Point(T,e); InsertChild(T,q,i,p); printf("层序遍历树T:\n"); LevelOrderTraverse(T,vi); printf("\n删除树T中结点e的第i棵子树,请输入e i: "); scanf("%c%d",&e,&i); q=Point(T,e); DeleteChild(T,q,i); printf("层序遍历树T:\n",e,i); LevelOrderTraverse(T,vi); printf("\n"); DestroyTree(T); }