引言
????二叉树的遍历方法有:前序遍历、中序遍历、后序遍历、层序遍历,其中前中后序遍历又有递归遍历和非递归遍历之分。 ????由于递归遍历算法本质上是借助系统栈实现的,因此,其非递归遍历算法的实现,也需要借助栈来实现。 ????对于层序遍历,因为是从根节点开始向下逐层、从左向右遍历的,要求最先遍历到的结点先被访问,即“先进先出”的一种特性,就可以借助一个队列完成层序遍历。 ????下面,先分别准备栈和队列两种数据结构的链式存储实现类( PS:此次使用C++语言编写代码,这样整体代码结构比较清晰,方法调用时候引用传值比较nice,有关一些基本操作的函数/方法管理起来也更加方便些,以下代码复制粘贴过去即可用)。
0 有关线性表结点定义-LinkNode
????LinkNode结点定义本来是放置在一个单独的头文件#include "LinkNode.h"里面的,采用类模板方式定义,是可以线性表通用的,被但是后来考虑到在树的一些操作过程中,需要同时在一个头文件里面引入栈和队列,为了偷懒,就直接将结点类作为栈和队列的内部类进行管理了。 ????结点定义代码如下,
template <typename T>
class LinkNode{
public:
void setData(T data){
this->data=data;
}
void setNext(LinkNode* next){
this->next=next;
}
T getData(){
return this->data;
}
LinkNode<T>* getNext(){
return this->next;
}
LinkNode(){
this->setData(0);
this->setNext(NULL);
}
LinkNode(T data,LinkNode* next){
this->setData(0);
this->setNext(NULL);
}
protected:
private:
T data;
LinkNode* next;
};
1 栈的链式存储结构实现-LinkedStack
????直接上代码,不解释原理。
template <typename T>
class LinkedStack{
public:
template <typename T>
class LinkNode{
public:
void setData(T data){
this->data=data;
}
void setNext(LinkNode* next){
this->next=next;
}
T getData(){
return this->data;
}
LinkNode<T>* getNext(){
return this->next;
}
LinkNode(){
this->setData(0);
this->setNext(NULL);
}
LinkNode(T data,LinkNode* next){
this->setData(0);
this->setNext(NULL);
}
protected:
private:
T data;
LinkNode* next;
};
void setHeader(LinkNode<T>* header){
if (this->header!=NULL)
{
this->header=header;
return;
}
std::cout<<"do setHeader Failed!"<<std::endl;
}
LinkNode<T>* getHeader(){
return this->header;
}
LinkedStack(){
this->header=new LinkNode<T>;
}
bool isEmpty(){
return this->header->getNext()==NULL?true:false;
}
LinkNode<T>* getTop(){
return this->header->getNext();
}
bool PushLinkedStack(T e){
LinkNode<T>* newNode=NULL;
newNode=new LinkNode<T>;
newNode->setData(e);
newNode->setNext(this->header->getNext());
this->header->setNext(newNode);
return true;
}
bool PopLinkedStack(T& e){
LinkNode<T>* p=NULL;
p=this->header->getNext();
this->header->setNext(p->getNext());
if (p!=NULL)
{
e=p->getData();
delete p;
}
return true;
}
protected:
private:
LinkNode<T>* header;
};
2 队列的链式存储结构实现-LinkedQueue
????直接上代码,不解释原理。
template <typename T>
class LinkedQueue{
public:
template <typename T>
class LinkNode{
public:
void setData(T data){
this->data=data;
}
void setNext(LinkNode* next){
this->next=next;
}
T getData(){
return this->data;
}
LinkNode<T>* getNext(){
return this->next;
}
LinkNode(){
this->setData(0);
this->setNext(NULL);
}
LinkNode(T data,LinkNode* next){
this->setData(0);
this->setNext(NULL);
}
protected:
private:
T data;
LinkNode* next;
};
LinkedQueue(){
this->front=new LinkNode<T>;
this->rear=this->front;
}
bool isEmpty(){
return this->front==this->rear?true:false;
}
void enQueue(T e){
LinkNode<T>* newNode=new LinkNode<T>;
newNode->setData(e);
this->rear->setNext(newNode);
this->rear=newNode;
}
void deQueue(T& e){
LinkNode<T>* node=NULL;
if (this->isEmpty()) return;
node=this->front->getNext();
e=node->getData();
this->front->setNext(node->getNext());
if (this->rear==node)
{
this->front=this->rear;
}
delete node;
}
protected:
private:
LinkNode<T>* front;
LinkNode<T>* rear;
};
3 二叉树的链式存储结构实现
????这部分也是直接上代码,不解释原理。
3.1 树的结点定义-TreeNode
template <typename T>
class TreeNode{
public:
void setData(T data){
if (typeid(data)==typeid(char))
{
this->data=data;
return;
}
std::cout<<"The Type is Wrong!"<<std::endl;
}
void setLchild(TreeNode* lchild){
if (lchild!=NULL)
{
this->lchild=lchild;
return;
}
this->lchild=NULL;
}
void setRchild(TreeNode* rchild){
if (rchild!=NULL)
{
this->rchild=rchild;
return;
}
this->rchild=NULL;
}
T getData(){
return this->data;
}
TreeNode* getLchild(){
return this->lchild;
}
TreeNode* getRchild(){
return this->rchild;
}
TreeNode(){
this->setData(0);
this->lchild=NULL;
this->rchild=NULL;
}
TreeNode(T data){
this->setData(data);
this->lchild=NULL;
this->rchild=NULL;
}
virtual void visit(){
std::cout<<" "<<this->data<<" "<<std::endl;
}
void preOrder(){
this->visit();
if (this->lchild!=NULL)
{
this->lchild->preOrder();
}
if (this->rchild!=NULL)
{
this->rchild->preOrder();
}
}
void inOrder(){
if (this->lchild!=NULL)
{
this->lchild->inOrder();
}
this->visit();
if (this->rchild!=NULL)
{
this->rchild->inOrder();
}
}
void postOrder(){
if (this->lchild!=NULL)
{
this->lchild->postOrder();
}
if (this->rchild!=NULL)
{
this->rchild->postOrder();
}
this->visit();
}
protected:
private:
T data;
TreeNode* lchild;
TreeNode* rchild;
};
3.2 二叉树定义
#include "TreeNode.h"
#include "LinkedStack.h"
#include "LinkedQueue.h"
template <typename T>
class BinaryTree{
public:
void setRoot(TreeNode<T>* root){
if (root!=NULL)
{
this->root=root;
return;
}
this->root=NULL;
}
TreeNode<T>* getRoot(){
return this->root;
}
protected:
private:
TreeNode<T>* root;
};
3.3 前中后序遍历-递归算法实现
????直接放在binaryTree.h头文件中,作为BinaryTree类的成员方法即可。
void preOrder(){
if (this->root!=NULL)
{
this->root->preOrder();
}
}
void inOrder(){
if (this->root!=NULL)
{
this->root->inOrder();
}
}
void postOrder(){
if (this->root!=NULL)
{
this->root->postOrder();
}
}
3.4 前中后序遍历-非递归算法实现
????直接放在binaryTree.h头文件中,作为BinaryTree类的成员方法即可。
void preOrderWithStack(){
LinkedStack<TreeNode<T>*> *S=new LinkedStack<TreeNode<T>*>;
TreeNode<T>* p=this->root;
if (S==NULL) return;
while (p!=NULL||!S->isEmpty())
{
if (p!=NULL)
{
p->visit();
S->PushLinkedStack(p);
p=p->getLchild();
}else
{
S->PopLinkedStack(p);
p=p->getRchild();
}
}
if (S!=NULL)
{
delete S;
}
}
void inOrderWithStack(){
LinkedStack<TreeNode<T>*>* S=new LinkedStack<TreeNode<T>*>;
TreeNode<T>* p=this->root;
if (S==NULL)
{
return;
}
while (p!=NULL||!S->isEmpty())
{
if (p!=NULL)
{
S->PushLinkedStack(p);
p=p->getLchild();
}else
{
S->PopLinkedStack(p);
p->visit();
p=p->getRchild();
}
}
if (S!=NULL)
{
delete S;
}
}
void postOrderWithStack(){
LinkedStack<TreeNode<T>*>* S=new LinkedStack<TreeNode<T>*>;
TreeNode<T>* p=this->root;
TreeNode<T>* r=NULL;
if (S==NULL) return;
while (p!=NULL||!S->isEmpty())
{
if (p!=NULL)
{
S->PushLinkedStack(p);
p=p->getLchild();
}else
{
p=S->getTop()->getData();
if (p->getRchild()!=NULL&&r!=p->getRchild())
{
p=p->getRchild();
}else
{
S->PopLinkedStack(p);
p->visit();
r=p;
p=NULL;
}
}
}
if (S!=NULL) delete S;
}
3.5 层序遍历算法实现
????直接放在binaryTree.h头文件中,作为BinaryTree类的成员方法即可。
void levelOrder(){
if (this->root!=NULL)
{
LinkedQueue<TreeNode<T>*>* Q=new LinkedQueue<TreeNode<T>*>;
TreeNode<T>* p=this->root;
if (Q==NULL) return;
Q->enQueue(p);
while (!Q->isEmpty())
{
Q->deQueue(p);
p->visit();
if (p->getLchild()!=NULL)
Q->enQueue(p->getLchild());
if (p->getRchild()!=NULL)
Q->enQueue(p->getRchild());
}
if (Q!=NULL) delete Q;
}
}
4 代码测试
????此处手动创建二叉树结点,并设置树结点之间的关系,二叉树的结构如下图, ????测试代码如下,
#include "BinaryTree.h"
void test_binaryTree(){
TreeNode<char>* A=new TreeNode<char>('A');
TreeNode<char>* B=new TreeNode<char>('B');
TreeNode<char>* C=new TreeNode<char>('C');
TreeNode<char>* D=new TreeNode<char>('D');
TreeNode<char>* E=new TreeNode<char>('E');
TreeNode<char>* F=new TreeNode<char>('F');
TreeNode<char>* G=new TreeNode<char>('G');
TreeNode<char>* H=new TreeNode<char>('H');
TreeNode<char>* I=new TreeNode<char>('I');
H->setRchild(I);
C->setRchild(D);
G->setLchild(H);
B->setRchild(C);
E->setLchild(F);
E->setRchild(G);
A->setLchild(B);
A->setRchild(E);
BinaryTree<char>* bTree=new BinaryTree<char>;
bTree->setRoot(A);
bTree->levelOrder();
}
int main(int argc,char** argv){
test_binaryTree();
return 0;
}
5 测试结果
|