数据结构二叉树(C++)

数据结构二叉树

二叉树是树中特别重要的一种数据结构,在此整理了C++版本的二叉树,代码部分仅个人编写,不为最优方法。文章较长,完整源代码在最后。所实现的功能有如下。

  • 二叉树功能
    • 前序遍历建立二叉树
    • 寻找结点的左儿子
    • 寻找结点的右儿子
    • 寻找结点的父亲结点
    • 求二叉树的高度
    • 求二叉树的结点数目
    • 前、中、后序递归遍历
    • 前、中、后序非递归遍历(借助栈实现)
    • 层次遍历(借助队列)
    • 输出二叉树所有的叶子结点
    • 查找某个值的结点

二叉树结点以及二叉树的定义如下

struct BinTreeNode
{
	char data;
	BinTreeNode *leftChild, *rightChild;
	BinTreeNode() :leftChild(NULL), rightChild(NULL) {}
	BinTreeNode(char x, BinTreeNode *l = NULL, BinTreeNode *r = NULL) :data(x), leftChild(l), rightChild(r) {}
};
class BinaryTree
{
public:
	BinaryTree();
	~BinaryTree();
	bool IsEmpty();
	void preCreat(char endTag = '#');
	void preCreat(BinTreeNode *&root,char endTag='#');
	BinTreeNode* LeftChild(BinTreeNode *current);
	BinTreeNode* LeftChild(BinTreeNode *current,char item);
	BinTreeNode* RightChild(BinTreeNode *current);
	BinTreeNode* RightChild(BinTreeNode *root, char item);
	BinTreeNode* Parent(BinTreeNode *current);
	BinTreeNode* Parent(BinTreeNode *current,char item);
	int Hight();//返回二叉树的高度
	int Hight(BinTreeNode *subTree);
	int Size();//返回二叉树的结点数
	int Size(BinTreeNode *subTree);
	BinTreeNode*& getRoot();
	void preOrder();
	void preOrder(BinTreeNode *current);//前序递归遍历
	void inOrder();
	void inOrder(BinTreeNode *current); //中序递归遍历
	void postOrder();
	void postOrder(BinTreeNode *current);//后序递归遍历
	void preOrderStack();
	void preOrderStack(BinTreeNode* current);
	void inOrderStack();
	void inOrderStack(BinTreeNode* current);
	void postOrderStack();
	void postOrderStack(BinTreeNode* current);
	//使用栈进行遍历
	void PrintLeaves();
	void PrintLeaves(BinTreeNode *current);//输出所有的叶子结点
	void levelOrder();
	void levelOrder(BinTreeNode *root); //层次序遍历 借助队列
	BinTreeNode* Find(char item);//查找某个值的结点
	BinTreeNode* Find(BinTreeNode *current, char item);
	void destroy(BinTreeNode *root);
private:
	BinTreeNode *root;
};

构造函数

BinaryTree::BinaryTree():root(NULL){}

析构函数

BinaryTree::~BinaryTree()
{
	destroy(root);
}

destroy()函数

使用递归的方法销毁二叉树,先销毁左子树,再销毁右子树,最后删除根结点。
浏览destroy()声明可以发现,destroy()函数设为了共有,因此可以手动调用,也可以在程序结束时自动调用。

void BinaryTree::destroy(BinTreeNode *root)
{
	if (root == NULL)
		return;
	destroy(root->leftChild);
	destroy(root->rightChild);
	delete root;
}

判断二叉树是否为空

bool BinaryTree::IsEmpty()
{
	return root == NULL ? true : false;
}

前序遍历生成二叉树

此处有两种不同参数的函数,第一种显而易见,在二叉树的根结点上去创建二叉树,第二种是为了使用递归来创建二叉树,也可以实现在二叉树的子树上继续添加数据。

void BinaryTree::preCreat(char endTag)
{
	preCreat(root, endTag); 
}
void BinaryTree::preCreat(BinTreeNode *&root,char endTag)
{
	char element;
	cin >> element;
	if (element != endTag)
	{
		root = new BinTreeNode(element);
		assert(root != NULL);
		preCreat(root->leftChild,endTag);
		preCreat(root->rightChild,endTag);
	}
}

左儿子结点

第一种是在已知结点地址的情况下求左儿子
第二种是根据结点的数据域来找左儿子

BinTreeNode* BinaryTree::LeftChild(BinTreeNode *current)
{
	if (current == NULL || current->leftChild == NULL)//考虑空树的存在
		return NULL;
	return current->leftChild;
}
BinTreeNode* BinaryTree::LeftChild(BinTreeNode *current,char item)
{
	if (current == NULL)
		return NULL;
	if (current->data == item && current->leftChild != NULL)
		return current->leftChild;
	if (LeftChild(current->leftChild, item) != NULL)//要进行判断,等于NULL就不能返回了
		return LeftChild(current->leftChild, item);
	return LeftChild(current->rightChild, item);
	//此处写法不为最优,仅为节省时间,理解即可
	//可以令BinTreeNode *p=LeftChild(current->leftChild,item),对p进行判断和返回	
}

右儿子结点

第一种是在已知结点地址的情况下求右儿子
第二种是根据结点的数据域来找右儿子

BinTreeNode* BinaryTree::RightChild(BinTreeNode *current)
{
	if (current == NULL || current->rightChild == NULL)
		return NULL;
	return current->rightChild;
}
BinTreeNode* BinaryTree::RightChild(BinTreeNode *current, char item)
{
	if (current == NULL)
		return NULL;
	if (current->data == item && current->rightChild != NULL)
		return current->rightChild;
	if (RightChild(current->leftChild, item) != NULL)//也要判断,为NULL不能返回
		return RightChild(current->leftChild, item);
	return RightChild(current->rightChild, item);
}

父亲结点
如果结点有父亲指针会更方便,此处没有。

BinTreeNode* BinaryTree::Parent(BinTreeNode *current)
{
	if (root == NULL || current == root)
		return NULL;
	else
		return Parent(root, current->data);
}
BinTreeNode* BinaryTree::Parent(BinTreeNode* current, char item)
{
	if (current == NULL)
		return NULL;
	if (current->leftChild != NULL && current->leftChild->data == item)
		return current;
	else if (current->rightChild != NULL && current->rightChild->data == item)
		return current;
	else if (Parent(current->leftChild, item)!=NULL)
		return Parent(current->leftChild, item);
	return Parent(current->rightChild, item);

}
BinTreeNode *BinaryTree::Parent(BinTreeNode*subTree, BinTreeNode*current)
{
	if (subTree == NULL)
		return NULL;
	if (subTree->leftChild == current || subTree->rightChild == current)
		return subTree;
	BinTreeNode *p;
	p = Parent(subTree->leftChild, current);
	if (p != NULL)
		return p;
	else
		return Parent(subTree->rightChild, current);
}

二叉树的高度

此处可以求整个树的高度,也可以求子树的高度

int BinaryTree::Hight()
{
	return Hight(root);
}
int BinaryTree::Hight(BinTreeNode* subTree)
{
	if (subTree == NULL)
		return 0;
	else
	{
		int i = Hight(subTree->leftChild);
		int j = Hight(subTree->rightChild);
		return (i<j)?j+1:i+1;
	}
}

二叉树的结点个数

int BinaryTree::Size()
{
	return Size(root);
}
int BinaryTree::Size(BinTreeNode* subTree)
{
	if (subTree == NULL)
		return 0;
	else
		return 1 + Size(subTree->leftChild) + Size(subTree->rightChild);
}

返回二叉树的根结点

BinTreeNode*& BinaryTree::getRoot()
{
	return root;
}

这里采用了*&的方式,如果不理解可参考链接
指针与引用

前序递归遍历

第二种方式可以遍历子树

void BinaryTree::preOrder()
{
	preOrder(root);
}
void BinaryTree::preOrder(BinTreeNode *current)
{
	if (current == NULL)
		return;
	cout << current->data << " ";
	preOrder(current->leftChild);
	preOrder(current->rightChild);
}

中序递归遍历

void BinaryTree::inOrder()
{
	inOrder(root);
}
void BinaryTree::inOrder(BinTreeNode *current)
{
	if (current == NULL)
		return;
	inOrder(current->leftChild);
	cout << current->data << " ";
	inOrder(current->rightChild);
} 

后序递归遍历

void BinaryTree::postOrder()
{
	postOrder(root);
}
void BinaryTree::postOrder(BinTreeNode *current) 
{
	if (current == NULL)
		return;
	postOrder(current->leftChild);
	postOrder(current->rightChild);
	cout << current->data << " ";
}

求二叉树所有的叶子结点

void BinaryTree::PrintLeaves()
{
	PrintLeaves(root);
}
void BinaryTree::PrintLeaves(BinTreeNode *current)
{
	if (current == NULL)
		return;
	if (current->leftChild == NULL && current->rightChild == NULL)
		cout<< current->data<<" ";
	PrintLeaves(current->leftChild);
	PrintLeaves(current->rightChild);
}//输出所有的叶子结点  前序遍历输出

查找某个值的结点位置

BinTreeNode* BinaryTree::Find(char item)
{
	return Find(root, item);
}//查找某个值的结点
BinTreeNode* BinaryTree::Find(BinTreeNode *current, char item)
{
	if (current == NULL)
		return NULL;
	if (current->data == item)
		return current;
	if (Find(current->leftChild, item) != NULL)
		return Find(current->leftChild, item);//必须对左子树进行判断后再决定要不要返回,如果为空,不要返回,因为还没有遍历右子树
	else
		return Find(current->rightChild, item);
	//简化写法
	//return Find(current->leftChild, item) ? current->leftChild: Find(current->rightChild,item);
}//在以current为根结点的二叉树中去查找

在此有一点说明,观察类的函数声明,会发现基本所有的函数实现都用到了fun()和fun(参数)两种形式,原因是因为,使用含参函数是为了使用递归,实现函数比较简单,而使用fun()函数是为了调用简单,因为如果实现遍历或者查找等功能,直接使用对象调用即可,不需要参数。同时可以将getRoot()函数设置为私有成员,对root根结点进行更好的保护

层次遍历(借助队列实现)

  • 链式队列定义
    由于是关于队列的定义和实现,如果有需要可以参考下面的链接,此处不作分析。
    数据结构 队列
void BinaryTree::levelOrder()
{
	levelOrder(root);
}
void BinaryTree::levelOrder(BinTreeNode *Tree)
{
	if(Tree==NULL)
		return;
	Queue<BinTreeNode*> Q;
	Q.Enqueue(Tree);
	BinTreeNode *p;
	while (!Q.IsEmpty())
	{
		Q.Dequeu(p);
		cout << p->data << " ";
		if (p->leftChild != NULL)
			Q.Enqueue(p->leftChild);
		if (p->rightChild != NULL)
			Q.Enqueue(p->rightChild);
	}
} //层次序遍历 借助队列

借助栈实现前序遍历

  • 由于是关于栈的定义和实现,此处不做分析,如有需要可以参考下面的链接。
    数据结构 栈
void BinaryTree::preOrderStack()
{
	if (root == NULL)
		return;
	else
		preOrderStack(root);
}
void BinaryTree::preOrderStack(BinTreeNode *current)
{
	if (current == NULL)
		return;//二叉树为空则返回
	Stack<BinTreeNode*> S;
	BinTreeNode *p = current;
	while (p!=NULL||!S.IsEmpty())
	{
		while (p != NULL)
		{
			cout << p->data << " ";
			S.push(p);
			p = p->leftChild;
		}
		if (!S.IsEmpty())
		{
			S.pop(p);
			p = p->rightChild;
		}
	}
}

由于前序遍历和中序遍历没有太大差别(只改变输出位置即可),在此仅对前序遍历后后序遍历进行分析。
步骤如下

  1. 判断子树是否为空,为空则返回
  2. 创建一个存放二叉树结点指针(因为每一个二叉树结点都是用指针指向的)的栈。
  3. 由于是先序循环遍历,先遍历自身,再遍历左子树和右子树,此处(先不管循环条件)进入一个循环先输出根结点数据,同时p点入栈(因为右子树还没有访问),然后让p=p->next,保证了先遍历根结点然后访问左子树
  4. 当p==NULL时,说明从某个结点开始的左子树已经访问完了,然后判断栈是否为空,不为空,说明还有结点的右子树没有访问,取结点,让p=p->next。跳出,再去访问右子树的左子树!!
  5. 循环条件的判断为什么呢,首先栈不为空(因为如果栈不为空,说明还有结点的右子树没有访问),其次为p!=NULL(如果p!=NULL,说明该结点是需要访问的)
  6. 当p==NULL时,是表示某个结点的右儿子为空,如果此时栈也为空那么说明遍历结束。

借助栈实现中序遍历

void BinaryTree::inOrderStack()
{
	inOrderStack(root);
}
void BinaryTree::inOrderStack(BinTreeNode *current)
{
	if (current == NULL)
		return;
	Stack<BinTreeNode*> S;
	BinTreeNode *p = current;
	while (p != NULL || !S.IsEmpty())
	{
		while (p != NULL)
		{
			S.push(p);
			p = p->leftChild;
		}
		if (!S.IsEmpty())
		{
			S.pop(p);
			cout << p->data << " ";
			p = p->rightChild;
		}
	}
}

借助栈实现后序遍历

后序遍历要比栈的前序和中序遍历麻烦,因为在遍历时根结点的左右子树必须都要被访问过才可以访问根结点,但是每次出栈后该结点子树访问情况并不知道,因此需要设一个标志位

  • 仅对每个结点增加一个标志位Tag来说明上一次访问结点的子树是哪一个。
  • Tag为0说明上次访问的为左子树,为1说明访问的右子树。
struct postOrderNode
{
	BinTreeNode *ptr;
	int Tag;
	postOrderNode(BinTreeNode *p = NULL) :Tag(0), ptr(p) {};
};
void BinaryTree::postOrderStack()
{
	if(root!=NULL)
		postOrderStack(root);
}
void BinaryTree::postOrderStack(BinTreeNode *current)
{
	Stack<postOrderNode> S;
	if (current == NULL)
		return;
	postOrderNode q;
	BinTreeNode *p = current;
	do
	{
		while (p != NULL)
		{
			q.ptr = p;
			q.Tag = 0;
			S.push(q);
			p = p->leftChild;
		}
		int continue1 = 1;
		while(continue1&&!S.IsEmpty())
		{
			S.pop(q);
			p = q.ptr;
			switch (q.Tag)
			{
			case 0:q.Tag = 1;
				S.push(q);
				continue1 = 0;
				p = p->rightChild;
				break;
			case 1:cout << p->data << " "; break;
			}
		}
	}while (!S.IsEmpty());
}

由于个人比较喜欢用指针,所以可以发现所有的类型基本都是指针,唯独这个不是,是因为我在使用指针的时候结果不正确,思考好久还以为不能用,结果第二天整理了一下指针,回来又想了一次,发现还是可以用指针的,嘻嘻,代码如下。 请添加图片描述

void BinaryTree::postOrderStack(BinTreeNode *current)
{
	Stack<postOrderNode*> S;
	if (current == NULL)
		return;
	postOrderNode *q = new postOrderNode;//必须先定义一次并且new
	                         //即使第一个while循环不执行也不会报错
	                         //也会让q在new之后第二个while循环也可以访问
	                         //虽然出错的地方比较基础,但还是记录一下。
	BinTreeNode *p = current;
	do
	{
		while (p != NULL)
		{
			q = new postOrderNode;//每次都要new
			q->ptr = p;
			q->Tag = 0;
			S.push(q);
			p = p->leftChild;
		}
		int continue1 = 1;
		while (continue1 && !S.IsEmpty())
		{
			S.pop(q);
			p = q->ptr;
			switch (q->Tag)
			{
			case 0:q->Tag = 1;
				S.push(q);
				continue1 = 0;
				p = p->rightChild;
				break;
			case 1:cout << p->data << " "; break;
			}
		}
	} while (!S.IsEmpty());
}

步骤

  1. 如果根结点为空,退出。(此处不加也可以,因为进入循环后没有元素入栈,会跳出,函数结束),写上过程会比较清晰。
  2. 对根结点的左子树进行遍历,同时增加标志位,入栈,p=p->next。
  3. 当左子树为空的时候,出栈,判断标志位。
    如果为0,说明右子树没有被访问,那么continue1=0,p=p->rightChild,同时该结点入栈,跳出循环,对右子树进行 2 操作。
    如果为1,说明右子树已经访问过了,那么输出根结点,继续该循环。
    判断结束条件为 栈为空(根据程序可知,所有结点只有左右子树都被访问过之后才会不被入栈(switch 中case 1:访问后不再入栈)),所以当栈为空时,说明所有结点都被访问过了。

完整代码如下

#include<iostream>
#include<assert.h>
using namespace std;
struct BinTreeNode
{
	char data;
	BinTreeNode *leftChild, *rightChild;
	BinTreeNode() :leftChild(NULL), rightChild(NULL) {}
	BinTreeNode(char x, BinTreeNode *l = NULL, BinTreeNode *r = NULL) :data(x), leftChild(l), rightChild(r) {}
};
template <class T>
struct LinkNode
{
	T data;
	LinkNode* next;
	LinkNode() :next(NULL) {}
	LinkNode(T x, LinkNode<T> *n = NULL) :data(x), next(n) {}
};
template <class T>
struct stackNode
{
	T data;
	stackNode<T> *next;
	stackNode<T>():next(NULL){}
	stackNode<T>(T x, stackNode<T> *n = NULL) : data(x), next(n) {}
};

struct postOrderNode
{
	BinTreeNode *ptr;
	int Tag;
	postOrderNode(BinTreeNode *p = NULL) :Tag(0), ptr(p) {};
};


template<class T>
class Stack
{
public:
	Stack();
	~Stack();
	bool IsEmpty()const;
	bool pop(T& x);
	void push(const T& x);
	bool getTop(T& x)const;
	void makeEmpty();
	int getSize()const;
private:
	stackNode<T> *top;
};
template<class T>
Stack<T>::Stack()
{
	top = NULL;
}
template<class T>
Stack<T>::~Stack()
{
	makeEmpty();

}
template<class T>
bool Stack<T>::IsEmpty()const
{
	return (top == NULL) ? true : false;
}
template<class T>
bool Stack<T>::pop(T& x)
{
	if (IsEmpty())
		return false;
	stackNode<T> *p = top;
	x = top->data;
	top = top->next;
	delete p;

	return true;
}
template<class T>
void Stack<T>::push(const T&x)
{
	stackNode<T> *newNode =new stackNode<T>(x);
	assert(newNode != NULL);
	newNode->next = top;
	top = newNode;
	//简写
	//top=new stackNode<T>(x,top);
	//assert(top!=NULL);

}
template<class T>
bool Stack<T>::getTop(T& x)const
{
	if (IsEmpty())
		return false;
	x = top->data;
	return true;

}
template<class T>
void Stack<T>::makeEmpty()
{
	stackNode<T> *p;
	while (top != NULL)
	{
		p = top;
		top = top->next;
		delete p;
	}
}
template<class T>
int Stack<T>::getSize()const
{
	int size = 0;
	stackNode<T> *p = top;
	while (p != NULL)
	{
		size++;
		p = p->next;
	}
	return size;
}



template<class T>
class Queue
{
public:
	Queue();
	~Queue();
	bool Enqueue(const T& x);
	bool Dequeu(T &x);
	bool IsEmpty();
	int getSize()const;
	bool getFront(T& x)const;
	void makeEmpty();
private:
	LinkNode<T> *rear, *front;
};
template<class T>
Queue<T>::Queue():rear(NULL),front(NULL)
{}
template<class T>
Queue<T>::~Queue()
{
	makeEmpty();
}
template<class T>
bool Queue<T>::Enqueue(const T& x)
{
	LinkNode<T> *newNode =new LinkNode<T>(x);
	if (newNode == NULL)
		return false;
	if (front == NULL)
		front =rear= newNode;
	else
	{
		rear->next = newNode;
		rear = newNode;
	}
	return true;
}
template<class T>
bool Queue<T>::Dequeu(T &x)
{
	if (IsEmpty())
		return false;
	else
	{
		LinkNode<T> *p = front;
		x = front->data;
		front = front->next;
		delete p;
	}
	return true;
}
template<class T>
bool Queue<T>::IsEmpty()
{
	return (front == NULL) ? true : false;
}
template<class T>
int Queue<T>::getSize()const
{
	int size = 0;
	LinkNode<T> *p = front;
	while (p != NULL)
	{
		p = p->next;
		size++;
	}
	return size;
}
template<class T>
bool Queue<T>::getFront(T& x)const
{
	if (IsEmpty()==true)
		return false;
	x = front->data;
	return true;
}
template<class T>
void Queue<T>::makeEmpty()
{
	LinkNode<T> *p = front;
	while (front != NULL)
	{
		p = front;
		front = front->next;
		delete p;
	}
}



class BinaryTree
{
public:
	BinaryTree();
	~BinaryTree();
	bool IsEmpty();
	void preCreat(char endTag = '#');
	void preCreat(BinTreeNode *&root,char endTag='#');
	BinTreeNode* LeftChild(BinTreeNode *current);
	BinTreeNode* LeftChild(BinTreeNode *current,char item);
	BinTreeNode* RightChild(BinTreeNode *current);
	BinTreeNode* RightChild(BinTreeNode *root, char item);
	BinTreeNode* Parent(BinTreeNode *current);
	BinTreeNode* Parent(BinTreeNode *current,char item);
	int Hight();//返回二叉树的高度
	int Hight(BinTreeNode *subTree);
	int Size();//返回二叉树的结点数
	int Size(BinTreeNode *subTree);
	BinTreeNode*& getRoot();
	void preOrder();
	void preOrder(BinTreeNode *current);//前序递归遍历
	void inOrder();
	void inOrder(BinTreeNode *current); //中序递归遍历
	void postOrder();
	void postOrder(BinTreeNode *current);//后序递归遍历
	void preOrderStack();
	void preOrderStack(BinTreeNode* current);
	void inOrderStack();
	void inOrderStack(BinTreeNode* current);
	void postOrderStack();
	void postOrderStack(BinTreeNode* current);
	//使用栈进行遍历
	void PrintLeaves();
	void PrintLeaves(BinTreeNode *current);//输出所有的叶子结点
	void levelOrder();
	void levelOrder(BinTreeNode *root); //层次序遍历 借助队列
	BinTreeNode* Find(char item);//查找某个值的结点
	BinTreeNode* Find(BinTreeNode *current, char item);
	void destroy(BinTreeNode *root);
private:
	BinTreeNode *root;
};
BinaryTree::BinaryTree():root(NULL){}
BinaryTree::~BinaryTree()
{
	destroy(root);
}
bool BinaryTree::IsEmpty()
{
	return root == NULL ? true : false;
}
void BinaryTree::preCreat(char endTag)
{
	preCreat(root, endTag); 
}
void BinaryTree::preCreat(BinTreeNode *&root,char endTag)
{
	char element;
	cin >> element;
	if (element != endTag)
	{
		root = new BinTreeNode(element);
		assert(root != NULL);
		preCreat(root->leftChild,endTag);
		preCreat(root->rightChild,endTag);
	}
}
BinTreeNode* BinaryTree::LeftChild(BinTreeNode *current)
{
	if (current == NULL || current->leftChild == NULL)//考虑空树的存在
		return NULL;
	return current->leftChild;
}
BinTreeNode* BinaryTree::LeftChild(BinTreeNode *current,char item)
{
	if (current == NULL)
		return NULL;
	if (current->data == item && current->leftChild != NULL)
		return current->leftChild;
	if (LeftChild(current->leftChild, item) != NULL)
		return LeftChild(current->leftChild, item);
	return LeftChild(current->rightChild, item);	
}
BinTreeNode* BinaryTree::RightChild(BinTreeNode *current)
{
	if (current == NULL || current->rightChild == NULL)
		return NULL;
	return current->rightChild;
}
BinTreeNode* BinaryTree::RightChild(BinTreeNode *current, char item)
{
	if (current == NULL)
		return NULL;
	if (current->data == item && current->rightChild != NULL)
		return current->rightChild;
	if (RightChild(current->leftChild, item) != NULL)
		return RightChild(current->leftChild, item);
	return RightChild(current->rightChild, item);
}
BinTreeNode* BinaryTree::Parent(BinTreeNode *current)
{
	if (root == NULL || current == root)
		return NULL;
	else
		return Parent(root, current->data);
}
BinTreeNode* BinaryTree::Parent(BinTreeNode* current, char item)
{
	if (current == NULL)
		return NULL;
	if (current->leftChild != NULL && current->leftChild->data == item)
		return current;
	else if (current->rightChild != NULL && current->rightChild->data == item)
		return current;
	else if (Parent(current->leftChild, item)!=NULL)
		return Parent(current->leftChild, item);
	return Parent(current->rightChild, item);
		 
}
int BinaryTree::Hight()
{
	return Hight(root);

}//返回二叉树的高度
int BinaryTree::Hight(BinTreeNode* subTree)
{
	if (subTree == NULL)
		return 0;
	else
	{
		int i = Hight(subTree->leftChild);
		int j = Hight(subTree->rightChild);
		return (i<j)?j+1:i+1;
	}
}
int BinaryTree::Size()
{
	return Size(root);
}//返回二叉树的结点数
int BinaryTree::Size(BinTreeNode* subTree)
{
	if (subTree == NULL)
		return 0;
	else
		return 1 + Size(subTree->leftChild) + Size(subTree->rightChild);
}
BinTreeNode*& BinaryTree::getRoot()
{
	return root;
}
void BinaryTree::preOrderStack()
{
	if (root == NULL)
		return;
	else
		preOrderStack(root);
}
void BinaryTree::preOrderStack(BinTreeNode *current)
{
	if (current == NULL)
		return;//二叉树为空则返回
	Stack<BinTreeNode*> S;
	BinTreeNode *p = current;
	while (p!=NULL||!S.IsEmpty())
	{
		while (p != NULL)
		{
			cout << p->data << " ";
			S.push(p);
			p = p->leftChild;
		}
		if (!S.IsEmpty())
		{
			S.pop(p);
			p = p->rightChild;
		}
	}
}
void BinaryTree::inOrderStack()
{
	inOrderStack(root);
}
void BinaryTree::inOrderStack(BinTreeNode *current)
{
	if (current == NULL)
		return;
	Stack<BinTreeNode*> S;
	BinTreeNode *p = current;
	while (p != NULL || !S.IsEmpty())
	{
		while (p != NULL)
		{
			S.push(p);
			p = p->leftChild;
		}
		if (!S.IsEmpty())
		{
			S.pop(p);
			cout << p->data << " ";
			p = p->rightChild;
		}
	}
}
void BinaryTree::postOrderStack()
{
	if(root!=NULL)
		postOrderStack(root);
}
void BinaryTree::postOrderStack(BinTreeNode *current)
{
	Stack<postOrderNode> S;
	if (current == NULL)
		return;
	postOrderNode q;
	BinTreeNode *p = current;
	do
	{
		while (p != NULL)
		{
			q.ptr = p;
			q.Tag = 0;
			S.push(q);
			p = p->leftChild;
		}
		int continue1 = 1;
		while(continue1&&!S.IsEmpty())
		{
			S.pop(q);
			p = q.ptr;
			switch (q.Tag)
			{
			case 0:q.Tag = 1;
				S.push(q);
				continue1 = 0;
				p = p->rightChild;
				break;
			case 1:cout << p->data << " "; break;
			}
		}
	} while (!S.IsEmpty());
}
void BinaryTree::preOrder(BinTreeNode *current)
{
	if (current == NULL)
		return;
	cout << current->data << " ";
	preOrder(current->leftChild);
	preOrder(current->rightChild);
}//前序递归遍历
void BinaryTree::inOrder(BinTreeNode *current)
{
	if (current == NULL)
		return;
	inOrder(current->leftChild);
	cout << current->data << " ";
	inOrder(current->rightChild);
} //中序递归遍历
void BinaryTree::postOrder(BinTreeNode *current) 
{
	if (current == NULL)
		return;
	postOrder(current->leftChild);
	postOrder(current->rightChild);
	cout << current->data << " ";
}//后序递归遍历
void BinaryTree::preOrder()
{
	preOrder(root);
}
void BinaryTree::inOrder()
{
	inOrder(root);
}
void BinaryTree::postOrder()
{
	postOrder(root);
}
void BinaryTree::PrintLeaves()
{
	PrintLeaves(root);
}
void BinaryTree::PrintLeaves(BinTreeNode *current)
{
	if (current == NULL)
		return;
	if (current->leftChild == NULL && current->rightChild == NULL)
		cout<< current->data<<" ";
	PrintLeaves(current->leftChild);
	PrintLeaves(current->rightChild);
}//输出所有的叶子结点  前序遍历输出
void BinaryTree::levelOrder()
{
	levelOrder(root);
}
void BinaryTree::levelOrder(BinTreeNode *Tree)
{
	if(Tree==NULL)
		return;
	Queue<BinTreeNode*> Q;
	Q.Enqueue(Tree);
	BinTreeNode *p;
	while (!Q.IsEmpty())
	{
		Q.Dequeu(p);
		cout << p->data << " ";
		if (p->leftChild != NULL)
			Q.Enqueue(p->leftChild);
		if (p->rightChild != NULL)
			Q.Enqueue(p->rightChild);
	}

} //层次序遍历 借助队列
BinTreeNode* BinaryTree::Find(char item)
{
	return Find(root, item);
}//查找某个值的结点
BinTreeNode* BinaryTree::Find(BinTreeNode *current, char item)
{
	if (current == NULL)
		return NULL;
	if (current->data == item)
		return current;
	if (Find(current->leftChild, item) != NULL)
		return Find(current->leftChild, item);//必须对左子树进行判断后再决定要不要返回,如果为空,不要返回,因为还没有遍历右子树
	else
		return Find(current->rightChild, item);


	//简化写法
	//return Find(current->leftChild, item) ? current->leftChild: Find(current->rightChild,item);
}//在以current为根结点的二叉树中去查找
void BinaryTree::destroy(BinTreeNode *root)
{
	if (root == NULL)
		return;
	destroy(root->leftChild);
	destroy(root->rightChild);
	delete root;
}
int main()
{}

全部内容到此结束,所有函数都经过测试,应该没有错误,如果有错误或者读者有认为可以修改的地方,请指正。下面是几组测试样例,供大家使用。

  1. A##
  2. (空二叉树)##
  3. ABD##EG###C#F##
  4. ABC##DE#G##F###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值