数据结构之二叉树的存储与遍历

二叉树的定义与基本的概念(设计思路)

二叉树是n (n≥0)个结点的有限集合。

  • 每个节点最多有两个子节点,分别称为左子节点和右子节点。

  • 左子节点和右子节点可以为空。

  • 二叉树的子树也是二叉树。

用到的基本概念

  • 节点的度:一个节点含有子树的个数
  • 叶节点:度为0的节点称为叶节点,又称为终端节点
  • 分支节点:度不为0的节点,又称为非终端节点
  • 父节点:若一个节点含有子节点,则这个节点成为其子节点的父节点,又称为双亲结点
  • 子节点:一个节点含有的子树的根节点称为该节点的子节点,又称为孩子节点
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点
  • 树的度:一棵树中,最大的节点的度称为树的度
  • 节点的层次:从根节点开始定义,根为第1层,根的子节点为第2层,以此类推
  • 树的高度或深度:树中节点的最大层次
  • 堂兄弟节点:双亲在同一层的节点互为堂兄弟
  • 节点的祖先:从根到该节点所经分支上的所有节点
  • 子孙节点:以某节点为根的子树中任一节点都称为该节点的子孙

 二叉树性质

  • 若二叉树具有第k层的结点,那么第k层结点数的取值范围是多少?[1, 2^k-1^] 
  • 高度为h (h>=0)的二叉树至多有2^h^ - 1个结点
  • 设二叉树叶子结点数为n~0~,度为2的结点数为n~2~,则有:n~0~= n~2~+ 1。
  • 结点数为n的完全二叉树的高度为 \log_{2}n+1

特殊二叉树

满二叉树

  • 深度为h且具有2^h^-1个结点的二叉树

  • 每一层都容纳了该层所能容纳的最大结点数结点的二叉树

  • 没有度数为1的结点,且叶子结点均分布在最大层的二叉树

完全二叉树

  • 除去最大层是一棵满二叉树

  • 最大层上的结点向左充满

  • 叶子只可能分布在最大层和次大层上。

  • 度为1的结点至多有1个。

  • 一棵满二叉树一定是一棵完全二叉树,而一棵完全二叉树不一定是一棵满二叉树。

  • 对于具有相同结点数的二叉树而言,完全二叉树的高度一定是其中最小的

 

  c存储与遍历的实现

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct Node 
{
	char data;				//顶点数据
	struct Node* LChild;	//左边的指针
	struct Node* RChild;	//右边的指针
}TREE,*LPTREE;
LPTREE createNode(char data) 
{
	LPTREE newNode = (LPTREE)malloc(sizeof(TREE));
	assert(newNode);//判断是否为空
	newNode->data = data;
	newNode->LChild = NULL;
	newNode->RChild = NULL;
	return newNode;
}
//呆瓜式创建
void insertNode(LPTREE parent, LPTREE LChild, LPTREE RChild) 
{
	parent->LChild = LChild;
	parent->RChild = RChild;
}//创建一颗小小的树
//递归法打印
//1.前序 : 根左右
void preOrder(LPTREE root) 
{
	if (root != NULL) 
	{
		printf("%c", root->data);
		preOrder(root->LChild);
		preOrder(root->RChild);
	}
}
//2.中序: 左根右
void midOrder(LPTREE root) 
{
	if (root != NULL) 
	{
		midOrder(root->LChild);
		printf("%c", root->data);
		midOrder(root->RChild);
	}
}
//3.后序: 左右根
void  lastOrder(LPTREE root) 
{
	if (root != NULL) 
	{
		lastOrder(root->LChild);
		lastOrder(root->RChild);
		printf("%c", root->data);
	}
}
//递归创建
void createTree(LPTREE* T)
{
	char userKey = 0;
	scanf_s("%c", &userKey, 1);//传入数据
	//ABD##EG###C#FH###
	if (userKey == '#') //输入为#为空
	{
		*T = NULL;
	}
	else 
	{
		*T = (LPTREE)malloc(sizeof(TREE));
		assert(*T);
		(*T)->data = userKey;
		createTree(&(*T)->LChild);
		createTree(&(*T)->RChild);
	}
}
//非递归遍历
//1.层次遍历//重点学习
void layerOrder(LPTREE root) 
{
	LPTREE pmove = root;
	//队列需要的
	LPTREE queue[1024];
	int front = 0;
	int tail = 0;
	queue[tail++] = pmove;
	printf("%c", pmove->data);
	while (front != tail)
	{
		pmove = queue[front++];		//出队
		if (pmove->LChild != NULL)
		{
			queue[tail++] = pmove->LChild;
			printf("%c", pmove->LChild->data);
		}
		if (pmove->RChild != NULL) 
		{
			queue[tail++] = pmove->RChild;
			printf("%c", pmove->RChild->data);
		}
	}
}
//非递归法先序
void preOrderByStack(LPTREE root) 
{
	if (root == NULL)
		return;
	LPTREE pmove = root;
	//栈
	LPTREE stack[1024];
	int stackTop = -1;

	while (stackTop != -1 || pmove) 
	{
		//先走左边,边走边打印
		while (pmove != NULL) 
		{
			printf("%c", pmove->data);
			stack[++stackTop] = pmove;
			pmove = pmove->LChild;
		}
		//退出循环,到达空的位置,出栈找右边
		if (stackTop != -1) 
		{
			pmove = stack[stackTop--];
			pmove = pmove->RChild;
		}
	}
}
void midOrderByStack(LPTREE root) 
{
	if (root == NULL)
		return;

	LPTREE pmove = root;
	//栈
	LPTREE stack[1024];
	int stackTop = -1;

	while (pmove != NULL || stackTop != -1) 
	{
		while (pmove) 
		{
			stack[++stackTop] = pmove;
			pmove = pmove->LChild;
		}
		if (stackTop != -1) 
		{
			pmove = stack[stackTop--];
			printf("%c", pmove->data);
			pmove = pmove->RChild;
		}
	}
}
void lastOrderByStack(LPTREE root) 
{
	if (root == NULL)
		return;

	LPTREE pmove = root;
	//栈
	LPTREE stack[1024];
	int stackTop = -1;
	//1.先走到最左边
	while (pmove) 
	{
		stack[++stackTop] = pmove;
		pmove = pmove->LChild;
	}
	LPTREE lastvisited = NULL;
	while (stackTop != -1) 
	{
		pmove = stack[stackTop--];
		if (pmove->RChild == NULL || pmove->RChild == lastvisited) 
		{
			printf("%c", pmove->data);
			lastvisited = pmove;
		}
		else 
		{
			stack[++stackTop] = pmove;
			pmove = pmove->RChild;
			while (pmove) 
			{
				stack[++stackTop] = pmove;
				pmove = pmove->LChild;
			}
		}
	}
}
int main() 
{
#if 1
	//创建二叉树
	LPTREE A = createNode('A');
	LPTREE B = createNode('B');
	LPTREE C = createNode('C');
	LPTREE D = createNode('D');
	LPTREE E = createNode('E');
	LPTREE F = createNode('F');
	LPTREE G = createNode('G');
	LPTREE H = createNode('H');
	insertNode(A, B, C);
	insertNode(B, D, E);
	insertNode(E, G, NULL);
	insertNode(C, NULL, F);
	insertNode(F, H, NULL);
#elif 0
	LPTREE A = NULL;
	createTree(&A);
#endif
	preOrder(A);
	printf("\n");
	preOrderByStack(A);
	printf("\n");

	midOrder(A);
	printf("\n");
	midOrderByStack(A);
	printf("\n");

	lastOrder(A);
	printf("\n");
	lastOrderByStack(A);
	printf("\n");
	layerOrder(A);
	printf("\n");
	return 0;
}
递归法创建二叉树结果

 

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值