【二叉树->链表】二叉树结构转双向线性链表结构(先序遍历)

         二叉树存储结构属于非线性链表结构,转化成线性链表结构,能简化操作和理解。然而由非线性转线性需要对整个树遍历一次,不同的遍历方式转化结果页不一样。下面以先序为例。

方法一:

递归法。递归遍历二叉树,因为是双向链表,需要记录当前遍历元素的上一个元素。

方法二:

使用栈。先将遍历元素入栈,遍历完成后,出栈并连接成链表。

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\n");
		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("\n");
	
	system("pause");
	return 0;
}

测试样例:

/*先序为DLR(D:根节点,L:左子树,R:右子树)
  a
  / \
 b   c
 / \   / \
d * * e
*/
//先序序列为abdce,输入为abd***c*e**(*表示空格,代表空树)


对于一般树的情况,使用孩子兄弟表示法,将一般树表示成二叉树(结点存储结构为:指向本结点第一个孩子的指针,数值,指向同层下一个兄弟的指针),再由这个二叉树即可转换为线性链表结构。

对于森林的情况,将森林的每一棵树的根结点视为兄弟,再次使用孩子兄弟表示法转换成一般树结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值