二叉树存储结构属于非线性链表结构,转化成线性链表结构,能简化操作和理解。然而由非线性转线性需要对整个树遍历一次,不同的遍历方式转化结果页不一样。下面以先序为例。
方法一:
递归法。递归遍历二叉树,因为是双向链表,需要记录当前遍历元素的上一个元素。
方法二:
使用栈。先将遍历元素入栈,遍历完成后,出栈并连接成链表。
struct tree_node; struct tree_node{ struct tree_node *lc; struct tree_node *rc; char data; }; typedef struct tree_node treenode; void pre_create_tree(treenode **T){ //递归法 char datatemp; fflush(stdin); datatemp=getchar(); if(datatemp=='*'){ *T=NULL; } else{ if((*T=(treenode*)malloc(sizeof(treenode)))==NULL){ exit(0); } else{ (*T)->data=datatemp; (*T)->lc = (*T)->rc = NULL; pre_create_tree(&(*T)->lc); pre_create_tree(&(*T)->rc); } } } struct mytlist{ struct mytlist* front; struct mytlist* next; char data; }; typedef struct mytlist tlist; static tlist *cur_front=NULL; static tlist **cur_next; void pre_tree2list(treenode *tree, tlist** tlist_head){ //传递函数参数tlist_front必须传入NULL tlist* tlist_temp=NULL; if(tree==NULL){ *tlist_head = NULL; return; } if((tlist_temp=(tlist*)malloc(sizeof(tlist)))==NULL){ printf("malloc failed "); exit(0); } else{ tlist_temp->front = cur_front; *tlist_head = tlist_temp; tlist_temp->data = tree->data; cur_front = *tlist_head; cur_next = &(*tlist_head)->next; pre_tree2list(tree->lc, cur_next); pre_tree2list(tree->rc, cur_next); } } void visit_tlist(tlist* tlist_head){ while(tlist_head){ printf("%c ", tlist_head->data); tlist_head = tlist_head->next; } } int main(void) { treenode *mytree=NULL; tlist *mytlist=NULL; pre_create_tree(&mytree); pre_tree2list(mytree, &mytlist); visit_tlist(mytlist); printf(" "); system("pause"); return 0; }
测试样例:
/*先序为DLR(D:根节点,L:左子树,R:右子树)
a
/
b c
/ /
d * * e
*/
//先序序列为abdce,输入为abd***c*e**(*表示空格,代表空树)
对于一般树的情况,使用孩子兄弟表示法,将一般树表示成二叉树(结点存储结构为:指向本结点第一个孩子的指针,数值,指向同层下一个兄弟的指针),再由这个二叉树即可转换为线性链表结构。
对于森林的情况,将森林的每一棵树的根结点视为兄弟,再次使用孩子兄弟表示法转换成一般树结构。