二叉树

一、二叉树的定义

二叉树(Binary Tree)是n(n>= 0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两颗互不相交的、分别称为根节点的左子树和右子树的二叉树组成。

/*二叉树的二叉链表存储表示*/
typedef struct BiTNode
{
	int data;
	struct BiTNode * left, * right;
	BiTNode(int da = 0) : data(da), left(NULL), right(NULL) { };
}BiTNode, *BiTree;


二、二叉树的性质

    性质1    在二叉树的第i层上至多有2^(i-1)个结点(i >= 1)。

    性质2    深度为k的二叉树至多有2^k - 1个结点(k >= 1)。

    性质3    对任何一颗二叉树T,如果其终端结点数为n0, 度为2的结点数为n2,则n0 = n2 + 1。

    性质4    具有n个结点的完全二叉树的深度为

    性质5    对一颗有n个结点的完全二叉树的结点按层序编号(从第一层到第层,每层从左到右),则对任一结点i(1 <= i <= n),有

                (1)    如果i=1,则结点i是二叉树的根,无双亲。如果i>=1,其双亲结点为

                (2)    如果2i>n,则结点i无左孩子;否则其左孩子是结点2i

                (3)    如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1


三、特殊二叉树

满二叉树: 一颗深度为k且有2^k - 1个结点的二叉树称为满二叉树

完全二叉树: 深度为k,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时,称为完全二叉树。


四、二叉树的遍历

(1)    先序遍历

先序遍历二叉树的操作定义:若二叉树为空,则空操作;否则 (1)访问根结点; (2)先序遍历左子树;(3)先序遍历右子树。

/*先序遍历的递归实现*/
void PreOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	cout << T->data << " ";  // 访问根节点
	PreOrderTraverse(T->left); // 遍历左子树
	PreOrderTraverse(T->right); // 遍历右子树
}
/*******************************************************
* 二叉树先序遍历的非递归实现
* 具体过程:
		1. 首先申请一个新的栈,记为s
		2. 然后将二叉树压入s
		3. 如果s不为空,则弹出栈顶元素并打印根节点;
		   如果右子树不为空,则将右子树入栈;
		   如果左子树不为空,则将左子树入栈。
********************************************************/
void NRPreOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	stack<BiTree> s; // 创建一个栈
	BiTree p = NULL; // 用来存放从栈中弹出的二叉树
	s.push(T); 
	while (!s.empty()) {
		p = s.top(); // 返回栈顶元素
		cout << p->data << " "; // 打印当前树的根节点
		s.pop();
		if (p->right)
			s.push(p->right); // 右子树入栈
		if (p->left)
			s.push(p->left); // 左子树入栈
	}
}
/*先序遍历的非递归实现*/
void NRPreOrderTraverse(BiTree T)
{
	stack<BiTree> s;
	BiTree p = T;
	while (p != NULL || !s.empty()) {
		while (p != NULL) {
		    cout << p->data << " ";
		    s.push(p);
		    p = p->left;
		}
		if (!s.empty()) {
		    p = s.top();
		    s.pop();
		    p = p->right;
		}
	}
}


(2)    中序遍历

中序遍历二叉树的操作定义:若二叉树为空,则空操作;否则 (1)中序遍历左子树; (2)访问根结点;(3)中序遍历右子树。

/*中序遍历的递归实现*/
void InOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	PreOrderTraverse(T->left); // 遍历左子树
	cout << T->data << " ";  // 访问根节点
	PreOrderTraverse(T->right); // 遍历右子树
}
/*******************************************************
* 二叉树中序遍历的非递归实现
* 具体过程:
		1. 申请一个栈s,申请一个BiTree变量p并初始化为T
		2. 先把p压入栈s中,并依次把整棵树的左边界压入
		   栈中,即不断令p=p->left,然后重复步骤2
		3. 不断重复步骤2直到p为空,此时弹出栈顶元素,
		   令p等于栈顶元素值,打印根节点的值,然后令
		   p=p->right,然后重复步骤2
		4. 当s为空并且p为空时,整个过程结束
********************************************************/
void NRInOrderTraverse(BiTree T)
{
	stack<BiTree> s;
	BiTree p = T;
	while (p != NULL || !s.empty()) {
		while (p != NULL) {
			s.push(p);
			p = p->left;
		}
		if (!s.empty()) {
			p = s.top();
			cout << p->data << " ";
			s.pop();
			p = p->right;
		}
	}
}


(3)    后序遍历

后序遍历二叉树的操作定义:若二叉树为空,则空操作;否则 (1)后序遍历左子树; (2)后序遍历右子树;(3)访问根结点

/*后序遍历的递归实现*/
void PostOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	PreOrderTraverse(T->left); // 遍历左子树
	PreOrderTraverse(T->right); // 遍历右子树
	cout << T->data << " ";  // 访问根节点
}
/*******************************************************
* 二叉树后序遍历的非递归实现
* 具体过程:
	1. 申请两个栈s1,s2。s1初始化为T。
	2. 从s1中弹出栈顶元素,记为p,然后将p的左子树压入s1中,
	   然后将p的右子树压入s1中。
	3. 将p压入栈s2中
	4. 重复步骤2、步骤3。直到s1为空,过程停止
	5. 从s2中依次弹出并打印,打印的顺序就是后序遍历的顺序
********************************************************/
void NRPostOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	stack<BiTree> s1, s2; // 创建两个栈
	s1.push(T);
	BiTree p = NULL; // 用来存放从栈中弹出的二叉树
	while (!s1.empty()) {
		p = s1.top();
		s1.pop();
		if (p->left) s1.push(p->left);
		if (p->right) s1.push(p->right);
		s2.push(p);
	}
	while (!s2.empty()) {
		cout << s2.top()->data << " ";
		s2.pop();
	}
}
/*后序遍历的非递归实现*/
void NRPostOrderTraverse(BiTree T) {
	BiTree p = T;
	BiTree r = NULL;
	stack<BiTree> s;
	while (p != NULL || !s.empty()) {
		while (p != NULL) {
			s.push(p);
			p = p->left;
		}
		if (!s.empty()) {
			p = s.top();
			if (p->right != NULL && p->right != r)
				p = p->right;
			else {
				s.pop();
				cout << p->data << " ";
				r = p;
				p = NULL;
			}
		}
	}
}
/*二叉树后序遍历的非递归实现*/
void NRPostOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	stack<BiTree> s; // 创建栈
	s.push(T);
	BiTree p = NULL;
	BiTree r = NULL; // 记录最近一次弹出的元素
	while (!s.empty()) {
		p = s.top();
		if (p->left != NULL && r != p->left && r != p->right)
			s.push(p->left);
		else if (p->right != NULL && r != p->right)
			s.push(p->right);
		else {
			s.pop();
			cout << p->data << " ";
			r = p;
		}
	}	
}


(4)    层序遍历

从上到下,从左到右依次打印二叉树每个结点中存储的数据

/*二叉树的层序遍历*/
void PrintFromTopToBottom(BiTree T)
{
	if (T == NULL) return;
	deque<BiTree> p;
	p.push_back(T);

	while (p.size()) {
		BiTree pNode = p.front();
		p.pop_front();
		cout << pNode->data << " ";

		if (pNode->left)
			p.push_back(pNode->left);

		if (pNode->right)
			p.push_back(pNode->right);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值