算法:二叉树


一、树

1. 树的定义

树是由n (n>= 0)个结点组成的有限集合。如果n = 0,称为空树;如果n > 0,则

  • 有一个特定的称之为根(root)的结点,它只有直接后继,但没有直接前驱;
  • 除根以外的其它结点划分为m (m >= 0)个互不相交的有限集合T0,T1.….,Tm-1,每个集合又是一棵树,并且税之为根的子树(subTree)。每棵子树的根结点有且仅有一个直接前驱,但可以有0个或多个直接后继。

2. 树的特点

  • 1.节点的度:一个节点含有的子树的个数称为该节点的度;
  • 2.树的度:一棵树中,最大的节点的度称为树的度;
  • 3.叶节点或终端节点:度为零的节点;
  • 4.非终端节点或分支节点:度不为零的节点;
  • 5.父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
  • 6.孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
  • 7.兄弟节点:具有相同父节点的节点互称为兄弟节点;
  • 8.节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  • 9.深度:对于任意节点n,n的深度为从根到n的唯一路径长,根的深度为0;
  • 10.高度:对于任意节点n,n的高度为从n到一片树叶的最长路径长,所有树叶的高度为0;
  • 11.堂兄弟节点:父节点在同一层的节点互为堂兄弟;
  • 12.节点的祖先:从根到该节点所经分支上的所有节点;
  • 13.子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
  • 14.森林:由m (m>=0)棵互不相交的树的集合称为森林;
  • 15.树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树。反之是有序树。

二、 二叉树

1. 二叉树定义

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树、互不相交的二叉树组成。

2. 二叉树的性质

  • 若二叉树的层次从0开始,则在二叉树的第i层最多有 2^i 个结点。(i>= 0)[证明用数学归纳法]
  • 高度为k的二叉树最参有2k+1-1个结点。(k >= -1)[证明用求等比级数前k 项和的公式]
  • 对任何一棵二叉树,如果其叶结点个数为 n0,度为2的非叶结点个数为n2,则有n0=n2+1。

定义:满二叉树(Full Binary Tree):每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。

定义:完全二叉树(Complete Binary Tree):若设二叉树的高度为h,则共有h+1层。除第h层外,其它各层(0 ~ h-1)的结点数都达到最大个数,第h层从右向左连续缺若干结点,这就是完全二叉树。

度的计算示例
在这里插入图片描述

3. 二叉树的存储表示

  • 什么数据结构: Data_Structure = (D.S)。(数据+关系)
  • 数据的逻辑结构是对数据之间关系的描述,画图表示。
  • 数据元素之间的关系有两种不同的表示方法:顺序映象和非顺序映象,并由此得到两种不同的存储结构:顺序存储结构和链式存储结构。数据的存储结构是指数据的逻辑结构在计算机中的表示。

4. 二叉树遍历

所谓树的遍历,就是按某种次序访问树中的结点,要求每个结点访问一次且仅访问一次。设访问根结点记作v;遍历根的左子树记作L;遍历根的右子树记作 R;
中序遍历
前序遍历
后序遍历

在这里插入图片描述
在这里插入图片描述
递归实现中,前,后序遍历 代码示例

#include<iostream>
#include<vector>
using namespace std;

typedef char ElemType;

//二叉树
typedef struct BtNode
{
	ElemType data;
	struct BtNode* leftchild;
	struct BtNode* rightchild;
}BtNode, * BinaryTree;

//先序
void PreOrder(BtNode* p)
{
	if (p != NULL)
	{
		cout << p->data << " ";
		PreOrder(p->leftchild);
		PreOrder(p->rightchild);
	}
}
//中序
void InOrder(BtNode* p)
{
	if (p != NULL)
	{
		InOrder(p->leftchild);
		cout << p->data << " ";
		InOrder(p->rightchild);
	}
}
//后序
void PastOrder(BtNode* p)
{
	if (p != NULL)
	{
		PastOrder(p->leftchild);
		PastOrder(p->rightchild);
		cout << p->data << " ";
	}
}
BtNode* Buynode()
{
	BtNode* s = (BtNode*)malloc(sizeof(BtNode));
	if (NULL == s)
	{
		exit(1);
	}
	memset(s, 0, sizeof(BtNode));
	return s;
}
//创建二叉树
BtNode* CBTree1()
{
	BtNode* s = NULL;
	ElemType elem;
	cin >> elem;
	if (elem != '#')
	{
		s = Buynode();
		s->data = elem;
		s->leftchild = CBTree1();
		s->rightchild = CBTree1();
	}
	return s;
}
int FindIs(const char* is, int n, char ch)
{
	int pos = -1;
	for (int i = 0; i < n; ++i)
	{
		pos = i;
		break;
	}
	return pos;
}
BtNode* CreatePI(const char* ps, const char* is, int n)
{
	BtNode* s = NULL;
	if (n >= 1)
	{
		s = Buynode();
		s->data = ps[0];
		int pos = FindIs(is, n, ps[0]);
		if (pos == -1)
		{
			exit(1);
		}
		s->leftchild = CreatePI(ps + 1, is, pos);
		s->rightchild = CreatePI(ps + 1 + pos, is + 1 + pos, n - pos - 1);
	}
	return s;
}
BtNode* CreateBinartTreePI(const char* ps, const char* is, int n)
{
	if (ps == NULL || is == NULL || n <= 0)
	{
		return NULL;
	}
	else
	{
		return CreatePI(ps,is, n);
	}
}
BtNode* CreateIL(const char* is, const char* ls, int n)
{
	BtNode* s = NULL;
	if (n > 0)
	{
		s = Buynode();
		s->data = ls[n - 1];
		int pos = FindIs(is, n, ls[n - 1]);
		if (pos == -1)exit(1);
		s->leftchild = CreateIL(is, ls, pos);
		s->rightchild = CreateIL(is + pos + 1, ls + pos, n - pos - 1);
	}
	return s;
}
BtNode* CreateBinaryTreeIL(const char* is, const char* ls, int n)
{
	if (is == NULL || ls == NULL || n <= 0)
	{
		return NULL;
	}
	else
	{
		return CreateIL(is, ls, n);
	}
}
int main()
{
	char ps[] = { "ABCDEFGH" };
	char is[] = { "CBEDFAGH" };
	char ls[] = { "CEFDBHGA" };
	int n = strlen(ps);
	BinaryTree root = NULL;
	//root = CreateBinartTreePI(ps, is, n);
	root = CreateBinaryTreeIL(is, ls, n);
	PreOrder(root);
	cout << endl;
	InOrder(root);
	cout << endl;
	PastOrder(root);
	cout << endl;
	return 0;
}

运行结果
在这里插入图片描述
非递归实现中,前,后序遍历


在这里插入图片描述

//非递归实现——中序遍历
void NiceInOrder(BtNode* ptr)
{
	if (ptr == NULL) return;
	std::stack<BtNode*> st;
	while (ptr != NULL || !st.empty())
	{
		while (ptr != NULL)
		{
			st.push(ptr);
			ptr = ptr->leftchild;
		}
		ptr = st.top();
		st.pop();
		cout << ptr->data;
		ptr = ptr->rightchild;
	}
	cout << endl;
}
int main()
{
	char ps[] = { "ABCDEFGH" };
	char is[] = { "CBEDFAGH" };
	char ls[] = { "CEFDBHGA" };
	int n = strlen(ps);
	BinaryTree root = NULL;
	//root = CreateBinartTreePI(ps, is, n);
	root = CreateBinaryTreeIL(is, ls, n);

运行结果
在这里插入图片描述

5.

5.1 如何解决中序遍历中出现的判断右子树是否遍历问题?

  • 增加标志域
    在这里插入图片描述
  • 两个栈进行移动

5.2 按照下列顺序打印二叉树

在这里插入图片描述
代码示例

void ZLevelOrder(BtNode* ptr)
{
	if (ptr == NULL) return;
	stack<BtNode*> ast;
	stack<BtNode*> bst;
	ast.push(ptr);
	while (!ast.empty() || !bst.empty())
	{
		while (!ast.empty())
		{
			ptr = ast.top(); ast.pop();
			cout << ptr->data;
			if (ptr->leftchild != NULL)
			{
				bst.push(ptr->leftchild);
			}
			if (ptr->rightchild != NULL)
			{
				bst.push(ptr->rightchild);
			}
		}
		while (!bst.empty())
		{
			ptr = bst.top(); bst.pop();
			cout << ptr->data;
			if (ptr->rightchild != NULL)
			{
				ast.push(ptr->rightchild);
			}
			if (ptr->leftchild != NULL)
			{
				ast.push(ptr->leftchild);
			}
		}
	}
}

运行结果
在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值