二叉树的C++实现(前中后序和层次遍历,添加删除前中后序线索,中序线索下的一些操作,重构二叉树)

一、二叉树的特点:

1. 每个节点都有唯一的父节点;

2. 每个节点最多只有两个子节点,分别为左孩子和右孩子;


二、链式的建立:

1. 根据特点有:


图 2-1 二叉树节点

2. 定义节点类:

template<typename Type>
class BinTreeNode

{

private:
Type data;
BinTreeNode<Type> *leftchild;
BinTreeNode<Type> *rightchild;
FLAG_TYPE ltag;
FLAG_TYPE rtag;
};

3.定义二叉树类:

template<typename Type>
class BinTree
{

private:
BinTreeNode<Type> *root;
Type StopFlag;

};

三、二叉树的线索化:

添加相应的成员,将节点修改为可以添加线索的类型

typedef enum{LINK, THREAD }FLAG_TYPE;
template<typename Type>
class BinTreeNode
{
friend class BinTree<Type>;
public:
BinTreeNode() :data(Type()), leftchild(NULL), rightchild(NULL), ltag(LINK), rtag(LINK)
{}
BinTreeNode(Type d, BinTreeNode<Type> *l = NULL, BinTreeNode<Type> *r = NULL):
data(d), leftchild(l), rightchild(r), ltag(LINK), rtag(LINK)
{}
~BinTreeNode()
{}
private:
Type data;
BinTreeNode<Type> *leftchild;
BinTreeNode<Type> *rightchild;
FLAG_TYPE ltag;
FLAG_TYPE rtag;
};

四、完整源代码:

BinTree.h

#ifndef _BINTREE_H
#define _BINTREE_H

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

template<typename Type>
class Queue	//实现用于层次遍历需要的功能,也可以#include<queue>
{	//以前有写C语言语法的线性结构,和C++一起用感觉怪怪的所以写了个够用的
public:
	Queue(int sz = 50) :m_ncurrentsize(0), m_nmaxsize(sz)
	{
		if (sz > 0)
		{
			m_data = new Type[m_nmaxsize];
		}
	}
	~Queue()
	{
		delete[]m_data;
	}
public:
	void Push(Type x)
	{
		m_ncurrentsize++;
		for (int j = m_ncurrentsize; j > 0; --j)
		{
			m_data[j] = m_data[j - 1];
		}
		m_data[0] = x;
	}
	void Pop()
	{
		m_ncurrentsize--;
	}
	Type Get()
	{
		return m_data[m_ncurrentsize - 1];
	}
	bool IsEmpty()
	{
		return m_ncurrentsize == 0;
	}
private:
	Type *m_data;
	const int m_nmaxsize;
	int m_ncurrentsize;
};

template<typename Type>
class BinTree;

//typedef一个枚举类型,表示线索的形式
typedef enum{LINK, THREAD }FLAG_TYPE;
template<typename Type>
class BinTreeNode
{
	friend class BinTree<Type>;
public:
	BinTreeNode() :data(Type()), leftchild(NULL), rightchild(NULL), ltag(LINK), rtag(LINK)
	{}
	BinTreeNode(Type d, BinTreeNode<Type> *l = NULL, BinTreeNode<Type> *r = NULL):
		data(d), leftchild(l), rightchild(r), ltag(LINK), rtag(LINK)
	{}
	~BinTreeNode()
	{}
private:
	Type data;
	BinTreeNode<Type> *leftchild;
	BinTreeNode<Type> *rightchild;
	FLAG_TYPE ltag;
	FLAG_TYPE rtag;
};

typedef enum{ NOTH, PRIO, MID, POST }THREAD_TYPE;
template<typename Type>
class BinTree
{
public:
	BinTree() :root(NULL)		
	{}
	BinTree(Type ref) :StopFlag(ref)
	{}
	BinTree(BinTree<Type> &t)//构造结果为无线索二叉树
	{
		root = Copy(t.root);
		StopFlag = t.StopFlag;
	}
	BinTree& operator=(BinTree<Type> &t)//赋值结果为无线索二叉树
	{
		if (this == &t)
			return *this;
		Destory(root);
		root = Copy(t.root);
		StopFlag = t.StopFlag;
		return *this;
	}
	~BinTree()
	{
		Destory(root);
	}
public:
	int Depth()const
	{
		return Depth(root);
	}
	void CreateBinTree()
	{
		Destory(root);
		CreateBinTree(root);
	}
	void CreateBinTree(const char *str)
	{
		Destory(root);
		CreateBinTree(root,str);
	}
	//尽量使用好的函数名代替注释
	void CreateBy_VLR_LVR(const char*svlr,const char *slvr, int n)
	{
		Destory(root);
		CreateBy_VLR_LVR(root, svlr, slvr, n);
	}
	void CreateBy_LVR_LRV(const char*slvr, const char *slrv, int n)
	{
		Destory(root);
		CreateBy_LVR_LRV(root, slvr, slrv, n);
	}
	void CreateInPrioThread()
	{
		BinTreeNode<Type> *pre = NULL;
		CreateInPrioThread(root, pre);
		ttype = PRIO;
	}
	void CreateInMidThread()
	{
		BinTreeNode<Type> *pre = NULL;
		CreateInMidThread(root, pre);
		pre->rtag = THREAD;
		pre->rightchild = NULL;
		ttype = MID;
	}
	void CreateInPostThread()
	{
		BinTreeNode<Type> *pre = NULL;
		CreateInPostThread(root, pre);
		pre->ltag = THREAD;
		pre->leftchild = NULL;
		ttype = POST;
	}
	void ClearThread()
	{
		ClearThread(root);
		ttype = NOTH;
	}
	void PreOrder()const
	{
		PreOrder(root);
	}
	void InOrder()const
	{
		InOrder(root);
	}
	void PostOrder()const
	{
		PostOrder(root);
	}
	void LevelOrder()const
	{
		LevelOrder(root);
	}
	BinTreeNode<Type> *FirstAsInMidThread()const
	{
		return FirstAsInMidThread(root);
	}
	BinTreeNode<Type> *LastAsInMidThread()const
	{
		return LastAsInMidThread(root);
	}
	BinTreeNode<Type> *ParentAsInMidThread(BinTreeNode<Type> *cur)const
	{
		return ParentAsInMidThread(root, cur);
	}
	BinTreeNode<Type> *ParentAsInMidThread(Type x)const
	{
		return ParentAsInMidThread(root, FindAsInMidThread(x));
	}
	BinTreeNode<Type> *FindAsInMidThread(Type x)const
	{
		return FindAsInMidThread(root, x);
	}
	BinTreeNode<Type> *prioAsInMidThread(BinTreeNode<Type> *cur)const;
	BinTreeNode<Type> *NextAsInMidThread(BinTreeNode<Type> *cur)const;

private:
	//如果要求下一个函数参数与上一个函数的调用有关,加指针的引用真实太有必要了
	void CreateBinTree(BinTreeNode<Type> *&t, const char *&str);
	void CreateBinTree(BinTreeNode<Type> *&t);
	void CreateBy_VLR_LVR(BinTreeNode<Type> *&t, const char* svlr, const char* slvr, int n);
	void CreateBy_LVR_LRV(BinTreeNode<Type> *&t, const char* slvr, const char* slrv, int n);
	int Depth(BinTreeNode<Type> *t)const;
	void PreOrder(BinTreeNode<Type> *t)const;
	void InOrder(BinTreeNode<Type> *t)const;
	void PostOrder(BinTreeNode<Type> *t)const;
	void LevelOrder(BinTreeNode<Type> *t)const;
	void Destory(BinTreeNode<Type> *t);
	BinTreeNode<Type> * Copy(BinTreeNode<Type> *t);
	void CreateInPrioThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre);
	void CreateInMidThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre);
	void CreateInPostThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre);
	void ClearThread(BinTreeNode<Type> *t);
	BinTreeNode<Type> *FirstAsInMidThread(BinTreeNode<Type> *t)const;
	BinTreeNode<Type> *LastAsInMidThread(BinTreeNode<Type> *t)const;
	BinTreeNode<Type> *FindAsInMidThread(BinTreeNode<Type> *t, Type &x)const;
	BinTreeNode<Type> *ParentAsInMidThread(BinTreeNode<Type> *root, BinTreeNode<Type> *t)const;
private:
	BinTreeNode<Type> *root;
	Type StopFlag;
	THREAD_TYPE ttype;
};

template <typename Type>
void  BinTree<Type>::ClearThread(BinTreeNode<Type> *t)
{
	if (t != NULL)
	{
		if (t->ltag != THREAD)
			ClearThread(t->leftchild);
		else
		{
			t->ltag = LINK;
			t->leftchild = NULL;
		}
		if (t->rtag != THREAD)
			ClearThread(t->rightchild);
		else
		{
			t->rtag = LINK;
			t->rightchild = NULL;
		}
	}
}

template <typename Type>
BinTreeNode<Type> * BinTree<Type>::ParentAsInMidThread(BinTreeNode<Type> *root, BinTreeNode<Type> *t)const
{
	if (root == NULL || t == NULL || t == root)
		return NULL;
	BinTreeNode<Type> *p = t;
	for (; p->ltag != THREAD;)
		p = p->leftchild;
	p = p->leftchild;
	if ((p != NULL)&&(p->leftchild == t || p->rightchild == t))
			return p;
	p = t;
	for (; p->rtag != THREAD;)
		p = p->rightchild;
	return p->rightchild;
}


template <typename Type>
BinTreeNode<Type> * BinTree<Type>::FindAsInMidThread(BinTreeNode<Type> *t, Type &x)const
{
	if (t == NULL)
		return NULL;
	BinTreeNode<Type> *p = NULL;
	if (t->data == x)
		return t;
	else
	{
		if (t->ltag != THREAD)
			p = FindAsInMidThread(t->leftchild,x);
		if (p == NULL && t->rtag != THREAD)
			p = FindAsInMidThread(t->rightchild,x);
		return p;
	}
}

template <typename Type>
BinTreeNode<Type> * BinTree<Type>::NextAsInMidThread(BinTreeNode<Type> *cur)const
{
	if (cur == NULL)
		return NULL;
	if (cur->rtag == THREAD)
		return cur->rightchild;
	else
		return FirstAsInMidThread(cur->rightchild);
}

template <typename Type>
BinTreeNode<Type> * BinTree<Type>::FirstAsInMidThread(BinTreeNode<Type> *t)const
{
	if (t == NULL)
		return NULL;
	//中序线索第一个元素必为左子树的最左子节点
	while (t->ltag != THREAD)
	{
		t = t->leftchild;
	}
	return t;
}

template <typename Type>
BinTreeNode<Type> * BinTree<Type>::LastAsInMidThread(BinTreeNode<Type> *t)const
{
	if (t == NULL)
		return NULL;
	//中序线索最后一个元素必为右子树的最右子节点
	while (t->rtag != THREAD)
	{
		t = t->rightchild;
	}
	return t;
}

template <typename Type>
BinTreeNode<Type> *BinTree<Type>::prioAsInMidThread(BinTreeNode<Type> *cur)const
{
	if (cur == NULL)
		return NULL;
	if (cur->ltag == THREAD)
		return cur->leftchild;
	else
		return LastAsInMidThread(cur->leftchild);
}

template <typename Type>
void BinTree<Type>::CreateInPrioThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre)
{
	if (cur == NULL)
		return;

	if (cur->leftchild == NULL)
	{
		cur->ltag = THREAD;
		cur->leftchild = pre;
	}
		
	if (pre!= NULL && pre->rightchild == NULL)
	{
		pre->rtag = THREAD;
		pre->rightchild = cur;
	}

	pre = cur;
	if (cur->ltag == LINK)
		CreateInPrioThread(cur->leftchild, pre);

	if (cur->rtag == LINK)
		CreateInPrioThread(cur->rightchild, pre);

}

template <typename Type>
void BinTree<Type>::CreateInPostThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre)
{
	if (cur == NULL)
		return;
	CreateInPostThread(cur->rightchild, pre);//初始方向为右
	if (cur->rightchild == NULL)
	{
		cur->rtag = THREAD;
		cur-> rightchild= pre;
	}
	if (pre != NULL && pre-> leftchild== NULL)
	{
		pre->ltag = THREAD;
		pre->leftchild = cur;
	}
	pre = cur;
	CreateInPostThread(cur->leftchild, pre);
}

template <typename Type>
void BinTree<Type>::CreateInMidThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre)
{
	if (cur == NULL)
		return;
	CreateInMidThread(cur->leftchild, pre);//初始方向为左
	if (cur->leftchild == NULL)	
	{
		cur->ltag = THREAD;
		cur->leftchild = pre;
	}
	if (pre != NULL && pre->rightchild == NULL)
	{
		pre->rtag = THREAD;
		pre->rightchild = cur;
	}
	pre = cur;
	CreateInMidThread(cur->rightchild, pre);
}

template <typename Type>
void BinTree<Type>::CreateBy_LVR_LRV(BinTreeNode<Type> *&t, const char* slvr, const char* slrv, int n)
{
	if (n == 0)
		return;
	int i = 0;
	while (slrv[n - 1] != slvr[i])
	{
		++i;
	}
	//char *lvr = "CBEDF A GH"
	//char *lrv = "CEFDB HG A";
	t = new BinTreeNode<Type>(slvr[i]);
	CreateBy_LVR_LRV(t->rightchild, slvr + i + 1, slrv + i, n - i - 1);
	CreateBy_LVR_LRV(t->leftchild, slvr, slrv, i);
}

template <typename Type>
void BinTree<Type>::CreateBy_VLR_LVR(BinTreeNode<Type> *&t,const char* svlr,const char* slvr,int n)
{
	if (n == 0)
		return;
	int i = 0;
	while (svlr[0] != slvr[i])
	{
		++i;
	}
	//char *vlr = "ABCDEFGH";
	//char *lvr = "CBEDFAGH";
	t = new BinTreeNode<Type>(slvr[i]);
	CreateBy_VLR_LVR(t->leftchild, svlr + 1, slvr, i);
	CreateBy_VLR_LVR(t->rightchild, svlr + i + 1, slvr + i + 1, n - i - 1);
}

template <typename Type>
BinTreeNode<Type> * BinTree<Type>::Copy(BinTreeNode<Type> *t)
{
	if (t == NULL)
		return NULL;
	BinTreeNode<Type> *p = new BinTreeNode<Type>;
	p->data = t->data;
	if (t->ltag != THREAD)
		p->leftchild = Copy(t->leftchild);
	else
		p->leftchild = NULL;
	if (t->rtag != THREAD)
		p->rightchild = Copy(t->rightchild);
	else
		p->rightchild = NULL;
	return p;
}

template <typename Type>
void BinTree<Type>::Destory(BinTreeNode<Type> *t)
{
	if (t == NULL)
		return;
	if (t->ltag != THREAD)
		Destory(t->leftchild);
	if (t->rtag != THREAD)
		Destory(t->rightchild);
	delete t;
}

template <typename Type>
void BinTree<Type>::PreOrder(BinTreeNode<Type> *t)const
{
	if (t != NULL )
	{
		cout << t->data;
		//添加遍历线索后需要添加判断语句来结束递归
		if(t->ltag != THREAD)
			PreOrder(t->leftchild);
		if (t->rtag != THREAD)
			PreOrder(t->rightchild);
	}
}
template <typename Type>
void BinTree<Type>::CreateBinTree(BinTreeNode<Type> *&t, const char *&str)
{
	char ch = str[0];
	str++;
	if (ch == StopFlag)
	{
		t = NULL;
	}
	else
	{
		t = new BinTreeNode<Type>(ch);
		CreateBinTree(t->leftchild, str);
		CreateBinTree(t->rightchild, str);
	}
}

template <typename Type>
void BinTree<Type>::CreateBinTree(BinTreeNode<Type> *&t)
{
	Type item;
	cin >> item;
	if (item == StopFlag)
		t = NULL;
	else
	{
		t = new BinTreeNode<Type>(item);
		CreateBinTree(t->leftchild);
		CreateBinTree(t->rightchild);
	}
}

template <typename Type>
int BinTree<Type>::Depth(BinTreeNode<Type> *t)const
{
	int dleft, dright, max;
	if (t == NULL)
		return 0;
	else
	{
		dleft = Depth(t->leftchild);
		dright = Depth(t->rightchild);
		max = dleft > dright ? dleft : dright;
		return max + 1;
	}
}

template <typename Type>
void  BinTree<Type>::InOrder(BinTreeNode<Type> *t)const
{
	if (t != NULL)
	{
		if (t->ltag != THREAD)
			InOrder(t->leftchild);
		cout << t->data;
		if (t->rtag != THREAD)
			InOrder(t->rightchild);
	}
}

template <typename Type>
void BinTree<Type>::PostOrder(BinTreeNode<Type> *t)const
{
	if (t != NULL)
	{
		if (t->ltag != THREAD)
			PostOrder(t->leftchild);
		if (t->rtag != THREAD)
			PostOrder(t->rightchild);
		cout << t->data;
	}
}

template <typename Type>
void BinTree<Type>::LevelOrder(BinTreeNode<Type> *t)const
{
	Queue<BinTreeNode<Type>*> Que;
	Que.Push(t);
	BinTreeNode<Type>* s = NULL;
	while (!Que.IsEmpty())
	{
		s = Que.Get();
		cout << s->data;
		if (s->leftchild != NULL && s->ltag != THREAD)//要出它,便先入它的孩子
			Que.Push(s->leftchild);
		if (s->rightchild != NULL && s->rtag != THREAD)
			Que.Push(s->rightchild);
		Que.Pop();
	}
}

#endif
Test.cpp

#include"BinTree.h"

int main(int argc, char *argv[])
{
	char *ch = "ABC##DE##F##G#H##";
	BinTree<char> bin('#');
	bin.CreateBinTree(ch);
	bin.PreOrder();
	cout << endl;
	bin.InOrder();
	cout << endl;
	bin.PostOrder();
	cout << endl;
	bin.LevelOrder();
	cout << endl;
	cout << bin.Depth() << endl;
	//为bin添加中序线索
	bin.CreateInMidThread();
	//在中序中做一些查找操作
	BinTreeNode<char> *p1 = bin.FirstAsInMidThread();
	BinTreeNode<char> *p2 = bin.NextAsInMidThread(p1);
	BinTreeNode<char> *q1 = bin.LastAsInMidThread();
	BinTreeNode<char> *q2 = bin.prioAsInMidThread(q1);
	BinTreeNode<char> *pp = bin.FindAsInMidThread('H');
	BinTreeNode<char> *ppp = bin.ParentAsInMidThread(pp);
	BinTreeNode<char> *pppp = bin.ParentAsInMidThread('H');
	//修改后的遍历函数可以适应各种情况
	bin.PreOrder();
	cout << endl;
	bin.InOrder();
	cout << endl;
	bin.PostOrder();
	cout << endl;
	bin.LevelOrder();
	cout << endl;
	bin.ClearThread();

	char *vlr = "ABCDEFGH";
	char *lvr = "CBEDFAGH";
	char *lrv = "CEFDBHGA";
	BinTree<char> bin2('#');
	bin2.CreateBy_VLR_LVR(vlr, lvr, strlen(lvr));
	bin2.CreateInPrioThread();

	BinTree<char> bin3(bin2);
	bin3.CreateBy_LVR_LRV(lvr, lrv, strlen(lvr));
	bin3.CreateInPostThread();

	system("pause");
	return 0;
}
五、运行及测试结果:

图 5-1 添加中序线索的树示例

图 5-2 测试程序运行结果



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值