数据结构:二叉树的左右插入,前中后序遍历及计算叶子节点功能的实现(较为详细,含完整代码)

以下为稍详细的讲解,若需要完整代码可直接至文章底部

首先我们需要构造一个基本的二叉树

1.TreeNode类实现

class TreeNode  //书中的单个节点的类
{
	friend class Tree;
	friend class preorderIterator;   //互为友元
	friend int equal(TreeNode* a, TreeNode* b);
public:
	TreeNode(int = 0);
	TreeNode( TreeNode*);
private:
	TreeNode* LeftChild;    //每个节点的私有数据成员
	int data = 0;
	TreeNode* RightChild;
};

我们知道TreeNode类与Tree类互为friend,在此之外我向其中加入了preorderIterator类,用于通过Iterator的形式来实现二叉树的前序遍历;equal函数用于判断两棵二叉树是否相等。TreeNode类包含三个数据成员,易知为节点的左孩子,右孩子和该节点的数据。

2.Tree类实现

class Tree   //树类
{
	friend class preorderIterator;
	friend class TreeNode;
	friend int operator == (const Tree&,const  Tree&);
public:
	Tree(int = 0);
	Tree(const Tree&);   //拷贝构造函数

	~Tree();

	int count();   //count函数,用于计算树中的叶子的数量

	TreeNode* getRoot();    //返回TreeNode的私有数据成员root

	void leftInsert(TreeNode*, TreeNode*);   //在该节点后的左边插入
	void rightInsert(TreeNode*, TreeNode*);  //在该节点的右边插入

	void inorder();    //中序遍历
	void inorder(TreeNode*);

	void preorder();   //前序遍历
	void preorder(TreeNode*);

	void postorder();    //后序遍历
	void postorder(TreeNode*);

	void LevelOrder();   //层序遍历

	void deleteNode(TreeNode*);   //递归法删除每个结点

	TreeNode* copy(TreeNode*);
private:
	TreeNode* root;
};

Tree类的结构也是较为简单,其数据成员仅为root根节点即可,public中全部是待实现的函数

下一步实现各项功能

1.equal函数的具体实现(顺便实现运算符重载)

int equal(TreeNode* a, TreeNode* b)   //递归法判断两棵树是否相等,输入两棵树的根节点
{
	if ((!a) && (!b))
		return 1;
	if (a && b && (a->data == b->data)
		&& equal(a->LeftChild, b->LeftChild)
		&& equal(a->RightChild, b->RightChild))
		return 1;
	return 0;
}

int operator == (const Tree& s, const Tree& t)
{
	return equal(s.root, t.root);
}

可知equal函数的原理即是传入两棵树的根节点,递归逐步比较,最终return结果

2.Tree类的析构函数

Tree::~Tree()  //destructor
{
	stack<TreeNode*> stack;
	TreeNode *CurrentNode = new TreeNode(*root);
	while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
	{
		while(CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
		{
			stack.push(CurrentNode);
			TreeNode *n = new TreeNode(*CurrentNode);
			delete n;  //指向同一处后,删除
			CurrentNode = CurrentNode->LeftChild;
		}
		if(!stack.empty())
		{
			CurrentNode = stack.top();
			stack.pop();
			CurrentNode = CurrentNode->RightChild;
		}
	}
}

Tree类的析构函数运用到了堆栈,一边将找到的节点存到栈中一边接着沿着树向下(左孩子方向)探寻,delete掉本次存入的节点,进行下一次,直到树底;随后开始弹出栈中存入数据,寻找其右孩子。(实际上就类似前序遍历)

3.实现count函数,用于计算叶子节点的数量

int Tree::count()  //计算叶子的数量
{
	int count = 0;
	TreeNode* CurrentNode = root;
	stack<TreeNode*> stack;
	while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
	{
		while (CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
		{
			stack.push(CurrentNode);
			CurrentNode = CurrentNode->LeftChild;
			if (CurrentNode != nullptr)
			{
				if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr)  //判断是否为叶子
				{
					count += 1;
				}
			}
		}
		if (!stack.empty())
		{
			CurrentNode = stack.top();
			stack.pop();
			CurrentNode = CurrentNode->RightChild;
			if (CurrentNode != nullptr)
			{
				if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr)  //判断是否为叶子
				{
					count += 1;
				}
			}
		}
	}
	return count;
}

与析构函数原理类似,以前序遍历的方式遍历二叉树,若该节点非为nullpter则判断为存在,count+1,最终返回count值

4.实现TreeNode类的copy函数,用于实现二叉树的拷贝

TreeNode* Tree::copy(TreeNode* orignode)  //递归法拷贝
{
	if (orignode)
	{
		TreeNode* temp = new TreeNode;
		temp->data = orignode->data;
		temp->LeftChild = copy(orignode->LeftChild);  //再次进入copy函数
		temp->RightChild = copy(orignode->RightChild);
		return temp;
	}
	else return 0;
}

原理既是以递归的方式实现数据复制

5.inOrder中序遍历实现

void Tree::inorder()
{
	inorder(root);
}


void Tree::inorder(TreeNode* CurrentNode)//非递归表达用stack实现
{
	stack<TreeNode*> stack;
	while (CurrentNode || !stack.empty()) 
	{
		while (CurrentNode)
		{
			stack.push(CurrentNode);
			CurrentNode = CurrentNode->LeftChild;  //中序遍历,一直到leftChild的底部
		}
		if (!stack.empty())  //从栈中弹出,输出其rightChild
		{
			CurrentNode = stack.top();
			stack.pop();
			cout << CurrentNode->data << " ";
			CurrentNode = CurrentNode->RightChild;
		}
	}
}

6.preOrder前序遍历实现

void Tree::preorder()
{
	preorder(root);
}


void Tree::preorder(TreeNode* CurrentNode)
{
	stack<TreeNode*> stack;
	while (CurrentNode || !stack.empty()) 
	{
		while (CurrentNode)
		{
			stack.push(CurrentNode);
			cout << CurrentNode->data<<" " ;  //前序遍历,到达左边的底部同时输出左值
			CurrentNode = CurrentNode->LeftChild;
		}
		if (!stack.empty())
		{
			CurrentNode = stack.top();
			stack.pop();
			CurrentNode = CurrentNode->RightChild;
		}
	}
}

7.postOrder后序遍历实现

void Tree::postorder()
{
	postorder(root);
}

void Tree::postorder(TreeNode* CurrentNode)  //后序遍历
{
	if (CurrentNode)
	{
		postorder(CurrentNode->LeftChild);
		postorder(CurrentNode->RightChild);
		cout << CurrentNode->data<<" ";
	}
}

8.levelOrder层序遍历实现

void Tree::LevelOrder()   //层序遍历
{
	queue<TreeNode*> queue;
	TreeNode* CurrentNode = root;//初始化定于root
	queue.push(CurrentNode);
	while (CurrentNode)
	{
		cout << CurrentNode->data << " ";
		if (CurrentNode->LeftChild)
			queue.push(CurrentNode->LeftChild);
		if (CurrentNode->RightChild)
			queue.push(CurrentNode->RightChild);
		queue.pop();
		if (!queue.empty())  //用于判断队列里面是否还有元素
			CurrentNode = queue.front();
		else
			break;
	}
}

9.基本功能左右插入及节点删除

void Tree::leftInsert(TreeNode* x, TreeNode* addNode)
{
	if (x)
		x->LeftChild = addNode;
}

void Tree::rightInsert(TreeNode* x, TreeNode* addNode)
{
	if (x)
		x->RightChild = addNode;
}

void Tree::deleteNode(TreeNode* CurrentNode)   
{
	if (CurrentNode == NULL)
		return;
	TreeNode* left = CurrentNode->LeftChild;   //由树根至树叶递归删除
	TreeNode* right = CurrentNode->RightChild;
	delete CurrentNode;
	if (left)
		deleteNode(left);
	if (right)
		deleteNode(right);
}

可知在删除一个节点时需要考虑该节点的左右孩子,通过递归实现树的衔接

10.通过Iterator的方法实现前序遍历

class preorderIterator   //利用Iterator方法进行前序遍历
{
	friend class Tree;
	friend class TreeNode;
	
public:
	int Next()   //next函数,用于循环,获取返回data值
	{
		while ((CurrentNode)&&(CurrentNode->LeftChild != nullptr ))  //到达左边倒数第二个节点
		{
			stack.push(CurrentNode);
			int temp = CurrentNode->data;
			CurrentNode = CurrentNode->LeftChild;
			if (!c)   //判断语句,判断当前CurrentNode是否为树的最后一个leftChild,c为bool型全局变量
			{
				return temp;
			}
			if (c)
			{
				c = false;
			}
		}
		if ((CurrentNode) && (CurrentNode->LeftChild == nullptr)&&(!c))  //用于判断(子)树最后一个leftChild是否输出
			//防止该数重复输出(因为该数也会在stack块中输出)
		{
			c = true;  //修改布尔变量c,用于判断该数是否已输出
			return CurrentNode->data;
		}
		if (!stack.empty())
		{
		  CurrentNode = stack.top();
		  stack.pop();
		  CurrentNode = CurrentNode->RightChild;
		  if (CurrentNode == nullptr)
		  {
			return -1;  //为空时返回-1,-1会被滤去
		  }
		  else return CurrentNode->data;
		  }
		else return -1;
	} 
	preorderIterator(Tree* tree)  //constructor
	{
		t = tree;
		CurrentNode = t->root;
	}

private:
	Tree* t;
	stack< TreeNode* > stack;
	TreeNode* CurrentNode;
};

可知preorderIterator类中需要next()函数用来获取下一个节点,next函数中 c 为初始化为false的全局布尔变量,用于做flag;语句详细解释可参考注释。

以上即实现了二叉树的基本构造及各相关功能

下面贴上完整的代码

//实现前序遍历的非递归版本,通过preorder Iterator实现
// 实现完整的C++二叉树类,包含构造函数,拷贝构造函数,析构函数,四种方式的遍历函数
// 写出count()函数,用于计算二叉树的树叶数
// 写出递归方式的析构函数Destructor()
#include <stack>   //使用栈的遍历
#include<iostream>
#include<queue>   //不用栈的遍历
using namespace std;

bool c = false;   //全局布尔变量,用于后面preorderIterator中的判断

class TreeNode  //书中的单个节点的类
{
	friend class Tree;
	friend class preorderIterator;   //互为友元
	friend int equal(TreeNode* a, TreeNode* b);
public:
	TreeNode(int = 0);
	TreeNode( TreeNode*);
private:
	TreeNode* LeftChild;    //每个节点的私有数据成员
	int data = 0;
	TreeNode* RightChild;
};



class Tree   //树类
{
	friend class preorderIterator;
	friend class TreeNode;
	friend int operator == (const Tree&,const  Tree&);
public:
	Tree(int = 0);
	Tree(const Tree&);   //拷贝构造函数

	~Tree();

	int count();   //count函数,用于计算树中的叶子的数量

	TreeNode* getRoot();    //返回TreeNode的私有数据成员root

	void leftInsert(TreeNode*, TreeNode*);   //在该节点后的左边插入
	void rightInsert(TreeNode*, TreeNode*);  //在该节点的右边插入

	void inorder();    //中序遍历
	void inorder(TreeNode*);

	void preorder();   //前序遍历
	void preorder(TreeNode*);

	void postorder();    //后序遍历
	void postorder(TreeNode*);

	void LevelOrder();   //层序遍历

	void deleteNode(TreeNode*);   //递归法删除每个结点

	TreeNode* copy(TreeNode*);
private:
	TreeNode* root;
};



int equal(TreeNode* a, TreeNode* b)   //递归法判断两棵树是否相等,输入两棵树的根节点
{
	if ((!a) && (!b))
		return 1;
	if (a && b && (a->data == b->data)
		&& equal(a->LeftChild, b->LeftChild)
		&& equal(a->RightChild, b->RightChild))
		return 1;
	return 0;
}

int operator == (const Tree& s, const Tree& t)
{
	return equal(s.root, t.root);
}

TreeNode::TreeNode(int x)  //用于赋根节点的值
{
	data = x;
	LeftChild = 0;
	RightChild = 0;
}

TreeNode::TreeNode( TreeNode* treeNode)  //拷贝
{
	data = treeNode->data;
	LeftChild = treeNode->LeftChild;
	RightChild = treeNode->RightChild;
}

Tree::Tree(int x)
{
	root = new TreeNode(0);
}

Tree::Tree(const Tree& tree)
{
	root = copy(tree.root);
}

Tree::~Tree()  //destructor
{
	stack<TreeNode*> stack;
	TreeNode *CurrentNode = new TreeNode(*root);
	while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
	{
		while(CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
		{
			stack.push(CurrentNode);
			TreeNode *n = new TreeNode(*CurrentNode);
			delete n;  //指向同一处后,删除
			CurrentNode = CurrentNode->LeftChild;
		}
		if(!stack.empty())
		{
			CurrentNode = stack.top();
			stack.pop();
			CurrentNode = CurrentNode->RightChild;
		}
	}
}


int Tree::count()  //计算叶子的数量
{
	int count = 0;
	TreeNode* CurrentNode = root;
	stack<TreeNode*> stack;
	while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
	{
		while (CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
		{
			stack.push(CurrentNode);
			CurrentNode = CurrentNode->LeftChild;
			if (CurrentNode != nullptr)
			{
				if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr)  //判断是否为叶子
				{
					count += 1;
				}
			}
		}
		if (!stack.empty())
		{
			CurrentNode = stack.top();
			stack.pop();
			CurrentNode = CurrentNode->RightChild;
			if (CurrentNode != nullptr)
			{
				if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr)  //判断是否为叶子
				{
					count += 1;
				}
			}
		}
	}
	return count;
}

TreeNode* Tree::copy(TreeNode* orignode)  //递归法拷贝
{
	if (orignode)
	{
		TreeNode* temp = new TreeNode;
		temp->data = orignode->data;
		temp->LeftChild = copy(orignode->LeftChild);  //再次进入copy函数
		temp->RightChild = copy(orignode->RightChild);
		return temp;
	}
	else return 0;
}

TreeNode* Tree::getRoot()
{
	return root;
}

void Tree::inorder()
{
	inorder(root);
}


void Tree::inorder(TreeNode* CurrentNode)//非递归表达用stack实现
{
	stack<TreeNode*> stack;
	while (CurrentNode || !stack.empty()) 
	{
		while (CurrentNode)
		{
			stack.push(CurrentNode);
			CurrentNode = CurrentNode->LeftChild;  //中序遍历,一直到leftChild的底部
		}
		if (!stack.empty())  //从栈中弹出,输出其rightChild
		{
			CurrentNode = stack.top();
			stack.pop();
			cout << CurrentNode->data << " ";
			CurrentNode = CurrentNode->RightChild;
		}
	}
}

void Tree::preorder()
{
	preorder(root);
}


void Tree::preorder(TreeNode* CurrentNode)
{
	stack<TreeNode*> stack;
	while (CurrentNode || !stack.empty()) 
	{
		while (CurrentNode)
		{
			stack.push(CurrentNode);
			cout << CurrentNode->data<<" " ;  //前序遍历,到达左边的底部同时输出左值
			CurrentNode = CurrentNode->LeftChild;
		}
		if (!stack.empty())
		{
			CurrentNode = stack.top();
			stack.pop();
			CurrentNode = CurrentNode->RightChild;
		}
	}
}

void Tree::postorder()
{
	postorder(root);
}

void Tree::postorder(TreeNode* CurrentNode)  //后序遍历
{
	if (CurrentNode)
	{
		postorder(CurrentNode->LeftChild);
		postorder(CurrentNode->RightChild);
		cout << CurrentNode->data<<" ";
	}
}

void Tree::LevelOrder()   //层序遍历
{
	queue<TreeNode*> queue;
	TreeNode* CurrentNode = root;//初始化定于root
	queue.push(CurrentNode);
	while (CurrentNode)
	{
		cout << CurrentNode->data << " ";
		if (CurrentNode->LeftChild)
			queue.push(CurrentNode->LeftChild);
		if (CurrentNode->RightChild)
			queue.push(CurrentNode->RightChild);
		queue.pop();
		if (!queue.empty())  //用于判断队列里面是否还有元素
			CurrentNode = queue.front();
		else
			break;
	}
}

void Tree::leftInsert(TreeNode* x, TreeNode* addNode)
{
	if (x)
		x->LeftChild = addNode;
}

void Tree::rightInsert(TreeNode* x, TreeNode* addNode)
{
	if (x)
		x->RightChild = addNode;
}

void Tree::deleteNode(TreeNode* CurrentNode)   
{
	if (CurrentNode == NULL)
		return;
	TreeNode* left = CurrentNode->LeftChild;   //由树根至树叶递归删除
	TreeNode* right = CurrentNode->RightChild;
	delete CurrentNode;
	if (left)
		deleteNode(left);
	if (right)
		deleteNode(right);
}

class preorderIterator   //利用Iterator方法进行前序遍历
{
	friend class Tree;
	friend class TreeNode;
	
public:
	int Next()   //next函数,用于循环,获取返回data值
	{
		while ((CurrentNode)&&(CurrentNode->LeftChild != nullptr ))  //到达左边倒数第二个节点
		{
			stack.push(CurrentNode);
			int temp = CurrentNode->data;
			CurrentNode = CurrentNode->LeftChild;
			if (!c)   //判断语句,判断当前CurrentNode是否为树的最后一个leftChild,c为bool型全局变量
			{
				return temp;
			}
			if (c)
			{
				c = false;
			}
		}
		if ((CurrentNode) && (CurrentNode->LeftChild == nullptr)&&(!c))  //用于判断(子)树最后一个leftChild是否输出
			//防止该数重复输出(因为该数也会在stack块中输出)
		{
			c = true;  //修改布尔变量c,用于判断该数是否已输出
			return CurrentNode->data;
		}
		if (!stack.empty())
		{
		  CurrentNode = stack.top();
		  stack.pop();
		  CurrentNode = CurrentNode->RightChild;
		  if (CurrentNode == nullptr)
		  {
			return -1;  //为空时返回-1,-1会被滤去
		  }
		  else return CurrentNode->data;
		  }
		else return -1;
	} 
	preorderIterator(Tree* tree)  //constructor
	{
		t = tree;
		CurrentNode = t->root;
	}

private:
	Tree* t;
	stack< TreeNode* > stack;
	TreeNode* CurrentNode;
};



int main()
{
	Tree* tree = new Tree();
	TreeNode* node1 = new TreeNode(1);    //共9个结点
	TreeNode* node2 = new TreeNode(2);
	TreeNode* node3 = new TreeNode(3);
	TreeNode* node4 = new TreeNode(4);
	TreeNode* node5 = new TreeNode(5);
	TreeNode* node6 = new TreeNode(6);
	TreeNode* node7 = new TreeNode(7);
	TreeNode* node8 = new TreeNode(8);

	tree->leftInsert(tree->getRoot(), node1);  //构建二叉树
	tree->rightInsert(tree->getRoot(), node2);
	tree->leftInsert(node1, node3);
	tree->rightInsert(node1, node4);
	tree->leftInsert(node2, node5);
	tree->rightInsert(node2, node6);
	tree->leftInsert(node3, node7);
	tree->rightInsert(node3, node8);
	cout << "Output by inorder function : ";
	tree->inorder();  
	cout << endl;

	cout << "Output by postorder function : ";
	tree->postorder();
	cout << endl;

	cout << "Output by LevelOrder function : ";
	tree->LevelOrder();
	cout << endl;

	cout << "Output by preorder function : ";
	tree->preorder();
	cout << endl;

	preorderIterator* it = new preorderIterator(tree);
	cout <<"Output by preorder Iterator function : ";
	while (it)
	{
		int n = it->Next();
		if (n == -1)
			break;
		cout << n<<" ";
	}
	cout << endl;

	cout << "The leaf number is : ";
	cout << tree->count();
	cout << endl;

	cout << "The Tree has been destructed " << endl;
	system("pause");
	return 0;
}

发布了3 篇原创文章 · 获赞 2 · 访问量 1926

猜你喜欢

转载自blog.csdn.net/weixin_43960713/article/details/104077194