二叉树

:树是n(n>=0)个节点的有限集。n=0是称为空树。在任何一颗非空树中:(1)有且仅有一个特定的节点称为根节点;(2)当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1、T2、、、Tm,其中每一个集合又是一棵树。如图:

接下来看二叉树!!!

二叉树:每个结点至多只有两颗子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。

二叉树的特点:

  1. 每个节点最多有两个子树,所以二叉树中不存在度大于2 的节点。
  2. 左子树和右子树是有序的,顺序不能任意颠倒。

二叉树的五种基本形态:

  1. 空二叉树;
  2. 只有一个根节点;
  3. 根节点只有左子树;
  4. 根节点只有右子树;
  5. 根节点既有左子树又有右子树。

接下来我们认识一下特殊的二叉树。

  • 斜树:所有的节点只有左子树或右子树。
  • 满二叉树:在一颗二叉树中所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上。如图:
  • 满二叉树的特点:
  1. 叶子节点只能出现在最下一层。
  2. 非叶子节点的度一定是2.
  3. 在同样深度的二叉树中,满二叉树的节点个数更多,叶子树更多。
  • 完全二叉树:对一棵具有N个节点的二叉树按层序编号,如果编号为i与同样深度的满二叉树中编号为i的节点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。

  • 完全二叉树的特点:
  1. 叶子节点只能出现在最下面两层;
  2. 最下层的叶子一定集中在左部连续位置;
  3. 倒数第二层,若有叶子结点,一定都在右部连续位置。
  4. 如果节点的度为1,则该节点只有左孩子。
  5. 同样节点的二叉树,完全二叉树的深度最小。

二叉树的一些性质:

  1. 二叉树第i层上的结点数目最多为 2^(i-1)(i≥1)。
  2. 深度为k的二叉树至多有2^k-1个结点(k≥1)。
  3. 包含n个结点的二叉树的高度至少为log2 (n+1)。
  4. 在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。
  5. 如果对一棵有n个节点的完全二叉树对其节点进行层序编号则:
  • 如果i=1,则其为二叉树的根。若i>0,则双亲节点为i+1;
  • 如果2i>n,则节点i无左孩子,否则其左孩子为2i;
  • 如果2i+1>n,则节点i无右孩子,否则其右孩子为2i+1。

二叉树的存储结构:二叉链表。

二叉树每个节点最多有两个孩子,所以为它设计一个数据域和两个指针域。

typedef struct BiTNode    //结点结构
{
    int data;    //结点数据
    struct BiTNode *lchild,*rchild;    //左右孩子的指针
}BiTNode;

二叉树的实现:

#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
using namespace std;
typedef int ElemType;
//二叉树节点
class BTNode   //Binary Tree Node
{
public:
	ElemType data;
	BTNode* lchild;   //左孩子
	BTNode* rchild;   //右孩子
	BTNode(ElemType d, BTNode* left = NULL, BTNode* right = NULL)
		:data(d), lchild(left), rchild(right) {}
};
//二叉树
class BinaryTree
{
private:
	//根节点指针
	BTNode* Root;
	//节点个数
	int size;
public:
	//构造函数
	BinaryTree();
	BTNode* buildTree();
	//析构函数
	~BinaryTree();
	//求树的高度
	int height();
	//获取节点个数
	int getSize()
	{
		return size;
	}
	void getHeight(BTNode*, int, int&);
	//指定遍历方式
	void traverse();
	//前序遍历
	void preOrderWithoutRecursion();
	void preOrder();
	void preorder(BTNode*);
	//中序遍历
	void inOrderWithoutRecursion();
	void inOrder();
	void inorder(BTNode*);
	//后序遍历
	void postOrderWithoutRecursion();
	void postOrder();
	void postorder(BTNode*);
	//层次遍历
	void levelOrder();
	//判断树是否为空
	bool empty()
	{
		return Root == NULL;
	}
	//获取根节点
	BTNode* root()
	{
		return Root;
	}
	//查找指定节点
	bool find(ElemType);
	//获取父节点
	BTNode* parent(ElemType);
	//获取左孩子
	BTNode* lchild(ElemType);
	//获取右孩子
	BTNode* rchild(ElemType);
};

BinaryTree::BinaryTree()
{
	size = 0;
	cout << "输入根节点 ";
	Root = buildTree();
}
BTNode* BinaryTree::buildTree()
{
	ElemType data;
	BTNode* p = NULL;
	cin >> data;
	//输入0结束
	if (data == 0)
		return p;
	else
	{
		p = new BTNode(data);
		size++;
		if (!p)
		{
			cerr << "内存分配失败!" << endl;
			exit(0);
		}
		else
		{
			cout << "请输入 " << data << " 节点的左孩子 ";
			p->lchild = buildTree();
			cout << "请输入 " << data << " 节点的右孩子 ";
			p->rchild = buildTree();
		}
	}
	return p;
}
//析构函数
BinaryTree::~BinaryTree()
{
	queue<BTNode*> q;
	q.push(Root);
	BTNode* p = NULL;
	while (!q.empty())
	{
		p = q.front();
		q.pop();
		//左孩子不为空,则左孩子入队
		if (p->lchild)
			q.push(p->lchild);
		//右孩子不为空,则右孩子入队
		if (p->rchild)
			q.push(p->rchild);
		//释放内存
		delete p;
	}
}
//求树的高度
int BinaryTree::height()
{
	if (empty())
		return 0;
	int h = 0;
	getHeight(Root, 0, h);
	return h;
}
void BinaryTree::getHeight(BTNode* p, int level, int &h)
{
	if (p)
	{
		if (level > h)
			h = level;
		getHeight(p->lchild, level + 1, h);
		getHeight(p->rchild, level + 1, h);
	}
}
//指定遍历方式
void BinaryTree::traverse()
{
	int choice;
	cout << "输入遍历方式:0(前序)、1(中序)、2(后序)、3(层次):";
	cin >> choice;
	while (choice < 0 || choice > 3)
	{
		cout << "输的不对!请重新输入: ";
		cin >> choice;
	}
	switch (choice)
	{
	case 0:preOrder(); break;
	case 1:inOrder(); break;
	case 2:postOrder(); break;
	case 3:levelOrder(); break;
	}
}
//前序遍历:根->左->右
void BinaryTree::preOrder()
{
	BTNode* pnode = Root;
	preorder(pnode);
	cout << endl;
}
void BinaryTree::preorder(BTNode* p)
{
	if (p)
	{
		cout << setw(4) << p->data;
		preorder(p->lchild);
		preorder(p->rchild);
	}
}
//中序遍历:左->根->右
void BinaryTree::inOrder()
{
	BTNode* pnode = Root;
	inorder(pnode);
	cout << endl;
}
void BinaryTree::inorder(BTNode* p)
{
	if (p)
	{
		inorder(p->lchild);
		cout << setw(4) << p->data;
		inorder(p->rchild);
	}
}
//后序遍历:左->右->根
void BinaryTree::postOrder()
{
	BTNode* pnode = Root;
	postorder(pnode);
	cout << endl;
}
void BinaryTree::postorder(BTNode* p)
{
	if (p)
	{
		postorder(p->lchild);
		postorder(p->rchild);
		cout << setw(4) << p->data;
	}
}
//层次遍历
void BinaryTree::levelOrder()
{
	//使用STL中的队列
	queue<BTNode*> q;
	//根节点入队
	q.push(Root);
	BTNode* p = NULL;
	while (!q.empty())
	{
		p = q.front();
		//打印
		cout << setw(4) << p->data;
		q.pop();
		//左孩子不为空,则左孩子入队
		if (p->lchild)
			q.push(p->lchild);
		//右孩子不为空,则右孩子入队
		if (p->rchild)
			q.push(p->rchild);
	}
	cout << endl;
}
//查找指定节点
bool BinaryTree::find(ElemType data)
{
	if (!empty())
	{
		//按层次遍历查找
		queue<BTNode*> q;
		q.push(Root);
		BTNode* p = NULL;
		while (!q.empty())
		{
			p = q.front();
			//比较
			if (p->data == data)
				return true;
			q.pop();
			if (p->lchild)
				q.push(p->lchild);
			if (p->rchild)
				q.push(p->rchild);
		}
	}
	//在树空和不存在该节点的情况下,都返回false
	return false;
}
//获取父节点
BTNode* BinaryTree::parent(ElemType data)
{
	if (!empty())
	{
		//根节点的父节点为空
		if (Root->data == data)
			return NULL;
		stack<BTNode*> s;
		BTNode* p = Root;
		while (!s.empty() || p)
		{
			if (p)
			{
				if ((p->lchild && p->lchild->data == data) || (p->rchild && p->rchild->data == data))
					return p;
				s.push(p);
				p = p->lchild;
			}
			else
			{//左子树访问完后,访问右子树
				p = s.top();
				s.pop();
				p = p->rchild;
			}
		}
	}
	return NULL;
}
//获取左孩子
BTNode* BinaryTree::lchild(ElemType data)
{
	if (!empty())
	{
		//按层次遍历查找
		queue<BTNode*> q;
		q.push(Root);
		BTNode* p = NULL;
		while (!q.empty())
		{
			p = q.front();
			//比较
			if (p->data == data)
				return p->lchild;
			q.pop();
			if (p->lchild)
				q.push(p->lchild);
			if (p->rchild)
				q.push(p->rchild);
		}
	}
	//在树空和不存在该节点的情况下,都返回NULL
	return NULL;
}
//获取右孩子
BTNode* BinaryTree::rchild(ElemType data)
{
	if (!empty())
	{
		//按层次遍历查找
		queue<BTNode*> q;
		q.push(Root);
		BTNode* p = NULL;
		while (!q.empty())
		{
			p = q.front();
			//比较
			if (p->data == data)
				return p->rchild;
			q.pop();
			if (p->lchild)
				q.push(p->lchild);
			if (p->rchild)
				q.push(p->rchild);
		}
	}
	//在树空和不存在该节点的情况下,都返回NULL
	return NULL;
}


int main()
{
	cout << "******二叉树******" << endl;
	BinaryTree tree;
	cout << "树的高度是 " << tree.height() << endl;
	cout << "树中共有节点个数 " << tree.getSize() << endl;
	tree.traverse();
	ElemType data = 2;
	cout << "对节点 " << data << " 进行查询" << endl;
	cout << "存在于树中吗?";
	tree.find(data) ? cout << "Yes!" << endl : cout << "No!" << endl;
	BTNode* p = NULL;
	p = tree.parent(data);
	p ? cout << "父节点是 " << p->data << endl : cout << data << "是根节点,故并无父节点" << endl;
	p = tree.lchild(data);
	p ? cout << "左孩子是 " << p->data << endl : cout << "无左孩子!" << endl;
	p = tree.rchild(data);
	p ? cout << "右孩子是 " << p->data << endl : cout << "无右孩子!" << endl;
	system("pause");
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值