二叉树的基本操作 C语言

                            二叉树的各项基本操作C语言

                                      
struct tree_node{
	char id;
	struct tree_node *left;
	struct tree_node *right;
};

typedef struct tree_node TreeNode;
typedef struct tree_node *Tree;

下面的描述都用下图所示的这棵二叉树为例。

1、二叉树的遍历

二叉树的遍历有四种方式:前序遍历、中序遍历、后序遍历、层序遍历。

1.1、前序遍历

先访问根节点,再分别前序遍历左、右两棵子树。前序遍历的结果是:ABCDEF

代码以递归方式实现:

//前序遍历
void PreShow(Tree T)
{
	if (!T)
	{
		return;
	}
	
	printf("%c ", T->id);
	PreShow(T->left);
	PreShow(T->right);
}

1.2、中序遍历

先中序遍历左子树,然后访问根节点,最后中序遍历右子树。中序遍历的结果是:CBAEDF

//中序遍历
void MidShow(Tree T)
{
	if (!T)
	{
		return;
	}
	
	MidShow(T->left);
	printf("%c ", T->id);
	MidShow(T->right);
}

1.3、后序遍历

先后序遍历左子树,再后序遍历右子树,最后访问根节点。后序遍历的结果是:CBEFDA

//后序遍历
void BackShow(Tree T)
{
	if (!T)
	{
		return;
	}
	
	BackShow(T->left);
	BackShow(T->right);
	printf("%c ", T->id);
}

1.4、层序遍历

从根节点开始,逐层访问各子节点。层序遍历的结果是:ABDCEF

前、中、后序遍历都采用递归的方式,实际上也就是用到了栈。而层序遍历则用队列的方式实现,具体的步骤如下:

(1)初始化一个队列,二叉树的根节点进队,即插入队尾。

(2)队首的树节点出队,访问这个树节点。先看它有没有左孩子,如果有,就让左孩子进队。再看它有没有右孩子,如果有,就让右孩子也进队。

(3)重复过程(2),直到队列清空为止。

//层序遍历
void LevelShow(Tree T)
{
	if (!T)
	{
		return;
	}

	Queue m_queue;
	Queue *Q;
	QueueNode *p, *q;

	Q = &m_queue;
	InitQueue(Q); //队列初始化

	p = (QueueNode *)malloc(sizeof(QueueNode));
	p->next = NULL;
	p->treenode = T;
	InQueue(Q, p); //根节点进队

	while (!IsQueueEmpty(Q))
	{
		OutQueue(Q, &q); //当前队首节点出队
		printf("%c ", q->treenode->id);

		if (q->treenode->left) //左孩子非空,则左孩子进队
		{
			p = (QueueNode *)malloc(sizeof(QueueNode));
			p->next = NULL;
			p->treenode = q->treenode->left;
			InQueue(Q, p);
		}
		if (q->treenode->right) //右孩子非空,则右孩子进队
		{
			p = (QueueNode *)malloc(sizeof(QueueNode));
			p->next = NULL;
			p->treenode = q->treenode->right;
			InQueue(Q, p);
		}
	}
}

2、二叉树的生成

我采用输入前序序列的方式生成二叉树,但这里的前序序列并不等同于前序遍历。因为计算机需要知道哪些节点是空白节点,所以应该按下图的方式输入前序序列。


用*代表空白的节点,于是输入的前序序列是:ABC***DE**F**

//创建二叉树
void CreateTree(Tree *T)
{
	char ch;

	scanf("%c", &ch);
	if (ch == '*')
	{
		*T = NULL;
	}
	else
	{
		*T = (Tree)malloc(sizeof(TreeNode));
		(*T)->id = ch;
		CreateTree(&(*T)->left);
		CreateTree(&(*T)->right);
	}
}

3、二叉树的删除

先删除左子树,再删除右子树,最后删除根节点,采用递归实现。

//清除二叉树
void ClearTree(Tree *T)
{
	if (!*T)
	{
		return;
	}

	ClearTree(&(*T)->left);
	ClearTree(&(*T)->right);
	free(*T);
	*T = NULL;
}

4、获得二叉树的高度

如果二叉树只有根节点,那么它的高度就为1。否则二叉树的高度等于1+左、右子树高度的较大者。按这种方法递归实现。

//获得二叉树的高度
int GetHeight(Tree T)
{
	if (T)
	{
		return MaxOfTwo(GetHeight(T->left), GetHeight(T->right)) + 1;
	} 
	else
	{
		return 0;
	}
}

//两数较大值
int MaxOfTwo(int a, int b)
{
	if (a >= b)
	{
		return a;
	} 
	else
	{
		return b;
	}
}

5、获得二叉树的节点数

二叉树的节点数 = 左子树节点数 + 右子树的节点数 + 1。递归实现即可。

//获得二叉树的节点数
int GetNodeNumber(Tree T)
{
	if (T)
	{
		return GetNodeNumber(T->left) + GetNodeNumber(T->right) + 1;
	} 
	else
	{
		return 0;
	}
}

6、运行结果

输入前序序列后,会显示二叉树的高度、节点数、四种遍历的结果,最后删除二叉树。


7、完整代码

完整的代码如下:

#include <STDIO.H>
#include <STDLIB.H>

struct tree_node{
	char id;
	struct tree_node *left;
	struct tree_node *right;
};

struct queue_node{
	struct tree_node *treenode;
	struct queue_node *next;
};

struct queue{
	struct queue_node *front;
	struct queue_node *rear;
};

typedef struct tree_node TreeNode;
typedef struct tree_node *Tree;
typedef struct queue_node QueueNode;
typedef struct queue Queue;

void CreateTree(Tree *);
int GetHeight(Tree);
int MaxOfTwo(int, int);
int GetNodeNumber(Tree);
void PreShow(Tree);
void MidShow(Tree);
void BackShow(Tree);
void LevelShow(Tree);
void InitQueue(Queue *);
bool IsQueueEmpty(Queue *);
void InQueue(Queue *, QueueNode *);
void OutQueue(Queue *, QueueNode **);
void ClearTree(Tree *);
bool IsTreeEmpty(Tree);

int main(void)
{
	Tree t;

	printf("输入二叉树的前序遍历序列,用*代替空节点:\n");
	CreateTree(&t);
	
	printf("\n二叉树创建完毕,高度为%d,节点数为%d。", GetHeight(t), GetNodeNumber(t));
	
	printf("\n\n前序遍历:");
	PreShow(t);
	
	printf("\n\n中序遍历:");
	MidShow(t);
	
	printf("\n\n后序遍历:");
	BackShow(t);
	
	printf("\n\n层序遍历:");
	LevelShow(t);
	
	ClearTree(&t);
	if (IsTreeEmpty(t))
	{
		printf("\n\n二叉树已经删除。");
	}
	printf("\n\n");
	
	return 0;
}

//创建二叉树
void CreateTree(Tree *T)
{
	char ch;

	scanf("%c", &ch);
	if (ch == '*')
	{
		*T = NULL;
	}
	else
	{
		*T = (Tree)malloc(sizeof(TreeNode));
		(*T)->id = ch;
		CreateTree(&(*T)->left);
		CreateTree(&(*T)->right);
	}
}

//获得二叉树的高度
int GetHeight(Tree T)
{
	if (T)
	{
		return MaxOfTwo(GetHeight(T->left), GetHeight(T->right)) + 1;
	} 
	else
	{
		return 0;
	}
}

//两数较大值
int MaxOfTwo(int a, int b)
{
	if (a >= b)
	{
		return a;
	} 
	else
	{
		return b;
	}
}

//获得二叉树的节点数
int GetNodeNumber(Tree T)
{
	if (T)
	{
		return GetNodeNumber(T->left) + GetNodeNumber(T->right) + 1;
	} 
	else
	{
		return 0;
	}
}

//前序遍历
void PreShow(Tree T)
{
	if (!T)
	{
		return;
	}
	
	printf("%c ", T->id);
	PreShow(T->left);
	PreShow(T->right);
}

//中序遍历
void MidShow(Tree T)
{
	if (!T)
	{
		return;
	}
	
	MidShow(T->left);
	printf("%c ", T->id);
	MidShow(T->right);
}

//后序遍历
void BackShow(Tree T)
{
	if (!T)
	{
		return;
	}
	
	BackShow(T->left);
	BackShow(T->right);
	printf("%c ", T->id);
}

//层序遍历
void LevelShow(Tree T)
{
	if (!T)
	{
		return;
	}

	Queue m_queue;
	Queue *Q;
	QueueNode *p, *q;

	Q = &m_queue;
	InitQueue(Q); //队列初始化

	p = (QueueNode *)malloc(sizeof(QueueNode));
	p->next = NULL;
	p->treenode = T;
	InQueue(Q, p); //根节点进队

	while (!IsQueueEmpty(Q))
	{
		OutQueue(Q, &q); //当前队首节点出队
		printf("%c ", q->treenode->id);

		if (q->treenode->left) //左孩子非空,则左孩子进队
		{
			p = (QueueNode *)malloc(sizeof(QueueNode));
			p->next = NULL;
			p->treenode = q->treenode->left;
			InQueue(Q, p);
		}
		if (q->treenode->right) //右孩子非空,则右孩子进队
		{
			p = (QueueNode *)malloc(sizeof(QueueNode));
			p->next = NULL;
			p->treenode = q->treenode->right;
			InQueue(Q, p);
		}
	}
}

//初始化队列
void InitQueue(Queue *q)
{
	q->front = NULL;
	q->rear = NULL;
}

//队列是否为空
bool IsQueueEmpty(Queue *q)
{
	if (q->front)
	{
		return false;
	} 
	else
	{
		return true;
	}
}

//进队
void InQueue(Queue *q, QueueNode * p)
{
	if (IsQueueEmpty(q))
	{
		q->front = p;
		q->rear = p;
	} 
	else
	{
		q->rear->next = p;
		q->rear = p;
	}
}

//出队
void OutQueue(Queue *q, QueueNode **p)
{
	*p = q->front;

	if (q->front == q->rear) //只有1个节点
	{
		q->front = NULL;
		q->rear = NULL;
	} 
	else
	{
		q->front = q->front->next;
	}
}

//清除二叉树
void ClearTree(Tree *T)
{
	if (!*T)
	{
		return;
	}

	ClearTree(&(*T)->left);
	ClearTree(&(*T)->right);
	free(*T);
	*T = NULL;
}

//二叉树是否为空
bool IsTreeEmpty(Tree T)
{
	if (T)
	{
		return false;
	} 
	else
	{
		return true;
	}
}
  • 58
    点赞
  • 340
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值