二叉树的动态创建(#号法)和遍历

二叉树每个结点最多有2个孩子,所以为它设计一个数据域和2个指针域是比较自然的想法,我们称这样的链表叫做二叉链表

正常的情况下,二叉树的单独前序、中序、后续,都不能唯一的确定一个二叉树,因为前序和后续,能确定根结点,但是区分不开左右子树。

而中序没办法知道哪个是根结点。

但是我们通常使用二叉树的扩展来进行创建树,原因是扩展二叉树的前序和后续,都能确定唯一的二叉树,至于原因,我会再单独写一篇文章说明,而中序不能确定,这里暂时给出代码实现。

先直接上代码,这里只是实现了二叉树的生成和遍历,生成采用前序遍历,遍历采用三种方法

#include<iostream>
using namespace std;
//二叉树的二叉链表结点结构定义
typedef	struct BitNode
{
	int data;//数据域
	struct BitNode*lchild, *rchild;//左右孩子指针
}BitNode;
typedef	struct BitNode* BitTree;
//二叉树的先序遍历
void PreOrder(BitTree Node)
{
	if (Node == NULL)
	{
		return;
	}
	//先访问根结点
	printf("%c\n", Node->data);
	if (Node->lchild != NULL)
	{
		PreOrder(Node->lchild);
	}
	if (Node->rchild != NULL)
	{
		PreOrder(Node->rchild);
	}
	
	
}
//中序遍历
void InOrder(BitTree Node)
{
	if (Node == NULL)
	{
		return;
	}
	if (Node->lchild != NULL)
	{
		InOrder(Node->lchild);
	}
	//先访问根结点
	printf("%c\n", Node->data);
	if (Node->rchild != NULL)
	{
		InOrder(Node->rchild);
	}
}
//后续遍历
void PostOrder(BitTree Node)
{
	if (Node == NULL)
	{
		return;
	}
	
	if (Node->lchild != NULL)
	{
		PostOrder(Node->lchild);
	}
	if (Node->rchild != NULL)
	{
		PostOrder(Node->rchild);
	}
	//先访问根结点
	printf("%c\n", Node->data);
}

//创建一个二叉树
/*按照前序输入二叉树中结点的值*/
/*其中#表示空树,构造二叉链表 表示二叉树T*/
//传二级指针的目的是为了修改一级指针的值
void CreateBitTree(BitTree *T)
{
	char ch;
	scanf("%c", &ch);
	if (ch == '#')
	{
		*T = NULL;
	}
	else
	{
		*T = (BitTree)malloc(sizeof(BitNode));
		if (*T == NULL)
		{
			printf("error \n");
			return;
		}
		(*T)->data = ch;//生成根结点
		CreateBitTree(&(*T)->lchild);//构造左子树 
		CreateBitTree(&(*T)->rchild);//构造右子树
	}
}
int main(int argc, char *argv[])
{
	BitTree tmp = (BitTree)malloc(sizeof(BitNode));//相当于传入头指针
	CreateBitTree(&tmp);
	printf("enter end\n");

	printf("start preorder\n");
	PreOrder(tmp);

	printf("start inorder\n");
	InOrder(tmp);

	printf("start postorder\n");
	PostOrder(tmp);
	return 0;
}

输出结果如下:

 

下面的代码是用后续进行创建树,后续要用到栈的数据结构,代码如下:

#include<iostream>
#include<cstdlib>
#include<string>
#include<stack>
using namespace std;
#define OK		1
#define ERROR	0

typedef int Status;
typedef char TElemType;
typedef struct BiTNode {
	TElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

typedef char SElemType;

stack<char> S;

Status InitBiTree(BiTree *);
BiTree PreCreateBiTree(BiTree *);		//先序扩展序列递归建树 
BiTree PostCreateBiTree(BiTree *);		//后序扩展序列建树准备工作 
BiTree PostCreateBiTree2(BiTree *);		//后序扩展序列递归建树
Status PreOrder(BiTree);
Status InOrder(BiTree);
Status PostOrder(BiTree);



Status InitBiTree(BiTree *BT) {
	*BT = NULL;
	return 0;
}

//先序扩展序列递归建树 
BiTree PreCreateBiTree(BiTree *BT) {
	TElemType ch;
	scanf("%c", &ch);

	if (ch == '#') {
		*BT = NULL;
		return *BT;
	}
	else {
		*BT = (BiTNode *)malloc(sizeof(BiTNode));
		(*BT)->data = ch;
		(*BT)->lchild = PreCreateBiTree(&((*BT)->lchild));
		(*BT)->rchild = PreCreateBiTree(&((*BT)->rchild));
	}

	return *BT;
}

//后序扩展序列建树准备工作,接收字符入栈 
BiTree PostCreateBiTree(BiTree *BT) 
{
	TElemType ch=0;
	//scanf("%c", &ch);
	//S.push(ch);

	while (1) 
	{
		scanf("%c", &ch);
		if (ch == '\n')
			break;
		S.push(ch);
	}
	*BT = PostCreateBiTree2(&(*BT));
	return *BT;
}

//后序扩展序列递归建树
BiTree PostCreateBiTree2(BiTree *BT) 
{
	TElemType ch;
	ch = S.top();
	S.pop();
	if (ch == '#') 
	{
		*BT = NULL;
		return *BT;
	}
	else 
	{
		*BT = (BiTNode *)malloc(sizeof(BiTNode));
		(*BT)->data = ch;
		(*BT)->rchild = PostCreateBiTree2(&((*BT)->rchild));
		(*BT)->lchild = PostCreateBiTree2(&((*BT)->lchild));
	}
	return *BT;
}

Status PreOrder(BiTree BT) 
{
	if (BT) 
	{
		if (!(BT->data))
			return ERROR;
		printf("%c ", BT->data);
		PreOrder(BT->lchild);
		PreOrder(BT->rchild);
		return OK;
	}
	return ERROR;
}

Status InOrder(BiTree BT) 
{
	if (BT) 
	{
		if (!(BT->data))
			return ERROR;
		InOrder(BT->lchild);
		printf("%c ", BT->data);
		InOrder(BT->rchild);
		return OK;
	}
	return ERROR;
}

Status PostOrder(BiTree BT) {
	if (BT) 
	{
		if (!(BT->data))
			return ERROR;
		PostOrder(BT->lchild);
		PostOrder(BT->rchild);
		printf("%c ", BT->data);
		return OK;
	}
	return ERROR;
}

int main() {
	BiTree BT;
	int flag = 1, select = 0;
	InitBiTree(&BT);
	printf(" Please input:");
	BT = PostCreateBiTree(&BT);
	printf("Create BiTree successfully!\n\n");

	printf("\t*\tPlease select:                             *\n");
	printf("\t*\t1.PreOrder Traversal                       *\n");
	printf("\t*\t2.InOrder Traversal                        *\n");
	printf("\t*\t3.PostOrder Traversal                      *\n");
	printf("\t*\t7.Exit                                     *\n");

	scanf("%d", &select);
	switch (select)
	{
	case 1:printf("\n The PreOrder Traversal of Binary Tree is: ");
		PreOrder(BT); break;
	case 2:printf("\n The InOrder Traversal of Binary Tree is: ");
		InOrder(BT); break;
	case 3:printf("\n The PostOrder Traversal of Binary Tree is: ");
		PostOrder(BT); break;
	}
	printf("\n");
	return 0;
}

输出结果如下:

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 以下是C语言二叉树链式创建以及前序,中序和后序的遍历功能的代码,以及主函数菜单: ``` #include <stdio.h> #include <stdlib.h> // 定义二叉树结构体 typedef struct TreeNode { int data; // 数据域 struct TreeNode *left; // 左子树指针 struct TreeNode *right; // 右子树指针 } TreeNode; // 创建二叉树 TreeNode* createTree() { int data; scanf("%d", &data); if (data == -1) { // 输入-1表示该节点为空 return NULL; } TreeNode *node = (TreeNode*)malloc(sizeof(TreeNode)); // 动态分配内存 node->data = data; node->left = createTree(); // 递归创建左子树 node->right = createTree(); // 递归创建右子树 return node; } // 前序遍历 void preOrder(TreeNode *root) { if (root == NULL) { return; } printf("%d ", root->data); // 输出当前节点的数据 preOrder(root->left); // 递归遍历左子树 preOrder(root->right); // 递归遍历右子树 } // 中序遍历 void inOrder(TreeNode *root) { if (root == NULL) { return; } inOrder(root->left); // 递归遍历左子树 printf("%d ", root->data); // 输出当前节点的数据 inOrder(root->right); // 递归遍历右子树 } // 后序遍历 void postOrder(TreeNode *root) { if (root == NULL) { return; } postOrder(root->left); // 递归遍历左子树 postOrder(root->right); // 递归遍历右子树 printf("%d ", root->data); // 输出当前节点的数据 } // 主函数菜单 int main() { printf("请输入二叉树的节点数据,-1表示该节点为空:\n"); TreeNode *root = createTree(); // 创建二叉树 printf("前序遍历结果为:"); preOrder(root); // 前序遍历 printf("\n中序遍历结果为:"); inOrder(root); // 中序遍历 printf("\n后序遍历结果为:"); postOrder(root); // 后序遍历 printf("\n"); return ; } ``` ### 回答2: C语言的二叉树是一种常见的数据结构,可以在对问题进行求解时提供很好的支持。在此,我们将介绍二叉树的链式存储结构以及前序,中序和后序的遍历功能,并在主函数中设置相应的菜单以实现用户交互的功能。 一、二叉树链式存储结构 二叉树链式存储结构一般由一个结构体表示,代表着二叉树中的每一个节点,具体代码如下: ``` struct TreeNode{ struct TreeNode *lchild; struct TreeNode *rchild; int value; } ``` 该结构体中包括左孩子指针、右孩子指针以及节点的值。 二、二叉树的创建 链式存储结构的二叉树创建通常使用递归函数来实现,例如下面这段代码: ``` struct TreeNode *createBinaryTree(){ int value; struct TreeNode *node; scanf("%d", &value); if(value == -1){ node = NULL; }else{ node = (struct TreeNode*)malloc(sizeof(struct TreeNode)); node->value = value; node->lchild = createBinaryTree(); node->rchild = createBinaryTree(); } return node; } ``` 上面的代码通过递归函数实现了二叉树的创建,当输入的节点值为-1时,返回NULL,否则创建一个节点,并分别递归创建该节点的左右孩子。 三、二叉树遍历 二叉树遍历方式有三种:前序遍历、中序遍历和后序遍历。分别如下: 1.前序遍历:先根节点,再左孩子,最后右孩子 ``` void preorder(struct TreeNode *root){ if(root != NULL){ printf("%d ", root->value); preorder(root->lchild); preorder(root->rchild); } } ``` 在前序遍历中,我们先访问根节点,然后递归遍历左子树和右子树。 2.中序遍历:先左孩子,再根节点,最后右孩子 ``` void inorder(struct TreeNode *root){ if(root != NULL){ inorder(root->lchild); printf("%d ", root->value); inorder(root->rchild); } } ``` 在中序遍历中,我们先递归遍历左子树,然后访问根节点,最后递归遍历右子树。 3.后序遍历:先左孩子,再右孩子,最后根节点 ``` void postorder(struct TreeNode *root){ if(root != NULL){ postorder(root->lchild); postorder(root->rchild); printf("%d ", root->value); } } ``` 在后序遍历中,我们先递归遍历左子树,然后递归遍历右子树,最后访问根节点。 四、主函数菜单 接下来我们可以在主函数中实现一个简单的菜单功能,可以让用户选择创建二叉树并进行遍历操作。 ``` int main(){ struct TreeNode *root; int choice; while(1){ printf("\n请选择操作:\n1、创建二叉树\n2、前序遍历\n3、中序遍历\n4、后序遍历\n0、退出程序\n"); scanf("%d", &choice); switch(choice){ case 1: printf("请输入二叉树节点的值,-1表示空节点:\n"); root = createBinaryTree(); break; case 2: printf("前序遍历结果为:"); preorder(root); printf("\n"); break; case 3: printf("中序遍历结果为:"); inorder(root); printf("\n"); break; case 4: printf("后序遍历结果为:"); postorder(root); printf("\n"); break; case 0: printf("程序已退出...\n"); return 0; default: printf("输入有误,请重新输入!\n"); break; } } } ``` 在上述代码中,我们首先定义了一个包含循环的整型变量,用来实现菜单功能。具体来说,用户可以选择创建二叉树、前序遍历、中序遍历和后序遍历,或者退出程序。在此程序中,我们将createBinaryTree()函数返回的根节点赋值给root,然后用preorder()、inorder()和postorder()函数分别对该二叉树进行遍历,输出遍历结果。 综上所述,我们介绍了二叉树的链式存储结构以及前序,中序和后序的遍历方法,并在主函数中实现了一个简单的菜单功能,供用户进行交互操作。 ### 回答3: C语言中,二叉树是一种常见的数据结构,可以用链式存储方式来实现。链式存储方式即利用指针变量来存储二叉树中每个节点的父节点、左子节点和右子节点。本文将介绍如何使用链式存储方式创建二叉树,并实现前序、中序、后序遍历等基本功能,并且通过主函数菜单进行相应操作。 创建二叉树 首先,我们要创建一个二叉树,可以通过链式存储方式来实现,创建一个节点信息如下: typedef struct BiTreeNode{ char data; struct BiTreeNode *leftChild; struct BiTreeNode *rightChild; }BiTreeNode, *BiTree; 其中,data代表节点储存的数据,leftChild和rightChild分别代表该节点的左子节点和右子节点,采用指针的方式实现链式存储。 二叉树的创建可以采用递归的方式实现,具体过程如下: //创建二叉树 BiTree createBiTree(){ BiTree T; char c; c = getchar(); //获取用户输入的字符 if(c == '#'){ T = NULL; }else{ T = (BiTree)malloc(sizeof(BiTreeNode)); //为节点动态分配内存 T->data = c; //为节点赋值 T->leftChild = createBiTree(); //递归创建左子树 T->rightChild = createBiTree(); //递归创建右子树 } return T; } 在createBiTree()函数中,从用户输入中获取字符c。如果c等于‘#’,则表示当前节点为NULL,返回NULL。否则,为当前节点T动态分配内存,并将用户输入的字符赋值给T的data。接着,递归建立T的左子树和右子树。最后,返回节点T。 前序遍历 前序遍历是指从二叉树的根节点开始,先访问该节点,再先序遍历该节点的左子树,最后再前序遍历该节点的右子树。 void preOrderTraverse(BiTree T){ if(T){ printf("%c", T->data); //访问该节点 preOrderTraverse(T->leftChild); //前序遍历左子树 preOrderTraverse(T->rightChild); //前序遍历右子树 } } 在preOrderTraverse()函数中,如果节点T存在,则打印该节点的数据。接着,递归前序遍历T的左子树和右子树。 中序遍历 中序遍历是指从二叉树的根节点开始,先中序遍历该节点的左子树,再访问该节点,最后再中序遍历该节点的右子树。 void InOrderTraverse(BiTree T){ if(T){ InOrderTraverse(T->leftChild); //中序遍历左子树 printf("%c", T->data); //访问该节点 InOrderTraverse(T->rightChild); //中序遍历右子树 } } 在InOrderTraverse()函数中,如果节点T存在,则递归中序遍历T的左子树。接着,打印该节点的数据。最后,递归中序遍历T的右子树。 后序遍历 后序遍历是指从二叉树的根节点开始,先后序遍历该节点的左子树,再后序遍历该节点的右子树,最后访问该节点。 void PostOrderTraverse(BiTree T){ if(T){ PostOrderTraverse(T->leftChild); //后序遍历左子树 PostOrderTraverse(T->rightChild); //后序遍历右子树 printf("%c", T->data); //访问该节点 } } 在PostOrderTraverse()函数中,如果节点T存在,则递归后序遍历T的左子树和右子树。接着,打印该节点的数据。 主函数菜单 在实现了二叉树的创建和遍历功能后,我们可以在主函数中展示一个菜单,供用户进行相应的操作。 int main(){ BiTree T = NULL; printf("Please input the data of node in the binary tree.(# represent NULL):\n"); T = createBiTree(); //创建二叉树 printf("\nThe result of pre-order traversal is:\n"); preOrderTraverse(T); //前序遍历二叉树 printf("\nThe result of in-order traversal is:\n"); InOrderTraverse(T); //中序遍历二叉树 printf("\nThe result of post-order traverse is:\n"); PostOrderTraverse(T); //后序遍历二叉树 return 0; } 在主函数中,首先声明T,并提示用户输入节点信息。创建二叉树后,打印前序遍历、中序遍历和后序遍历的结果。 以上是关于C语言二叉树链式创建以及前序,中序和后序的遍历功能及主函数菜单的相关介绍。通过本文的学习可以了解链式存储的二叉树创建方法,以及三种不同的遍历方式。同时,我们还可以巧妙的调用以上三种方法,并且使用主函数菜单以体现程序的易读性和操作性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值