sean

厚积薄发,坚持到最后一分钟。

第五章 树和二叉树 笔记 完结

PS:对于递归实现的前序,中序,后序算法,无非是在递归时,根的访问位置不同而已,代码内容几乎相似。非递归算法实现时,当root指针或栈非空时,先循环考虑root是否为否执行相应的操作,对于栈判断是否为空,进行root的转换。前序,后序,中序的非递归算法区别无非是每棵树的根节点的输出时机不同而已,具体实现大同小异。

1.二叉树的前序遍历-------------------非递归实现算法(伪代码)和递归实现

  非递归实现伪代码:

1.栈s初始化(空栈);
2.循环直到root为空且栈s为空 
 2.1 当root不空时循环
  2.1.1 输出root->data;
     2.1.2 将指针root的值保存到栈中;
     2.1.3 继续遍历root的左子树(root=root->lchild)
 2.2 如果栈s不空,则
  2.2.1 将栈顶元素弹出至root(root=s.pop());
  2.2.2 准备遍历root的右子树(root=root->rchild); 

    代码:

template <class T>
void BiTree::PreOrder(BiNode<T> *root) {
  SeqStack<BiNode<T> *>  s;
     while (root!=NULL | | !s.empty())     {
         while (root!= NULL)         {
             cout<<root->data;
             s.push=root;
             root=root->lchild;  
         }
         if (!s.empty()) { 
             root=s.pop();
             root=root->rchild;  
         }
     }
}

 

递归实现:

template   <class T>
void   BiTree::PreOrder(BiNode<T> *root) 
{
        if (root ==NULL)  return;     
        else {
            cout<<root->data;         
            PreOrder( root->lchild );    
            PreOrder(  root->rchild);    
        }
 }

2.二叉树的建立伪代码:

1.按前序扩展遍历序列输入输入节点的值
2.如果输入节点之为“#”,则建立一棵空的子树
3.否则,根结点申请空间,将输入值写入数据域中,
4.以相同方法的创建根节点的左子树
5.以相同的方法创建根节点的右子树
递归方法

代码:

template <class T>
BiTree ::BiTree(){ 
      root=creat();
}

template <class T>
BiNode<T> * BiTree ::Creat(){
     BiNode<T> *root; char ch;
    cin>>ch;
    if (ch=='# ')     root=NULL; 
    else {
        root=new BiNode<T>; 
        root->data=ch;
        root->lchild=creat(); 
        root->rchild= creat(); 
    }  
  return root
}

3.

中序遍历---------递归算法

template <class T>
void BiTree::InOrder (BiNode<T> *root)
{
         if (root==NULL) return;     
         else {
               InOrder(root->lchild); 
               cout<<root->data; 
               InOrder(root->rchild);
         }
}

中序遍历--------非递归算法(伪代码):

1.栈s初始化(空栈);
2.循环直到root为空且栈s为空 
 2.1 当root不空时循环
        2.1.1 将指针root的值保存到栈中;
     2.1.2 继续遍历root的左子树(root=root->lchild)
 2.2 如果栈s不空,则
  2.2.1 将栈顶元素弹出至root(root=s.pop());
     2.2.2 输出root->data;
  2.2.3 准备遍历root的右子树(root=root->rchild); 

代码:

template <class T>
void BiTree::InOrderwithoutD(BiNode<T> *root)
{
    stack< BiNode<T> * > aStack;
    while (!aStack.empty() || root)
    {
        while (root) 
        {
            aStack.push(root);
            root = root->lchild;
        }
        if (!aStack.empty())
        {
            root = aStack.top();
            aStack.pop();
            cout << root->data;
            root = root->rchild;
        }
    }
}

4.

后序遍历-----------递归算法

template <class T>
void BiTree::PostOrder(BiNode<T> *root)
{ 
    if (root==NULL) return; 
    else {
         PostOrder(root->lchild); 
         PostOrder(root->rchild); 
         cout<<root->data;          
    }
}

后序遍历的非递归实现:一种你叫巧妙的方法

分析:对于每一个节点压入栈两次,再循环体中,每次弹出一个赋值给p,若p仍和栈的栈顶元素相似,说明它的孩子们还没有访问过,将孩子们加入栈中,否则访问p。也就是第一次弹出将p的孩子们压入栈,第二次弹出访问p。

template<class T>                      ///后序遍历
void BiTree<T>::PostOrder(BiNode<T> *root)
{
     stack<BiNode<T>* >astack;
     BiNode<T> *p=root;
     astack.push(p);
     astack.push(p);
     while(!astack.empty())
     {

         p=astack.top();
         astack.pop();
         if(!astack.empty()&&p==astack.top())
         {

               if(p->rchild) astack.push(p->rchild), astack.push(p->rchild);
               if(p->lchild) astack.push(p->lchild), astack.push(p->lchild);
         }
         else
         {
             cout<<p->data;
         }
     }


}

 

 

 通过递归方式建树并测试

代码:

#include<bits/stdc++.h>
using namespace std;
template <class T>
struct BiNode
{
    T  data;
    BiNode<T> *lchild, *rchild;
};
template <class T>
class BiTree
{
public:
    BiTree(){Creat(root);}
    void PreOrder() { PreOrder(root); }
    void InOrder() { InOrder(root); }
    void PostOrder() { PostOrder(root);}
    void LevelOrder(){LevelOrder(root);}
private:
    BiNode<T> *root;
    void Creat(BiNode<T> *& root);
    void Release(BiNode<T> *root);
    void PreOrder(BiNode<T> *root);
    void InOrder(BiNode<T> *root);
    void PostOrder(BiNode<T> *root);
    void LevelOrder(BiNode<T> *root);
};

template<class T>          ///建立二叉树
void BiTree<T>::Creat(BiNode<T>*&root)
{
    T ch;
    cin >> ch;
    if (ch == '#') root = NULL;
    else {
        root = new BiNode<T>;
        root->data = ch;
        Creat(root->lchild);
        Creat(root->rchild);
    }

}

template<class T>                      ///前序遍历
void BiTree<T>::PreOrder(BiNode<T> *root)
{
    if (root == NULL) return;
    else
    {
        cout << root->data;
        PreOrder(root->lchild);
        PreOrder(root->rchild);

    }
}

template<class T>                      ///中序遍历
void BiTree<T>::InOrder(BiNode<T> *root)
{
     if (root == NULL) return;
     else
     {

        InOrder(root->lchild);
        cout << root->data;
        InOrder(root->rchild);

     }
}

template<class T>                      ///后序遍历
void BiTree<T>::PostOrder(BiNode<T> *root)
{
     if (root == NULL) return;
     else
     {

         PostOrder(root->lchild);
         PostOrder(root->rchild);
         cout << root->data ;

     }
}

template<class T>
void BiTree<T>::Release(BiNode<T>* root)
{
    if (root != NULL) {
        Release(root->lchild);
        Release(root->rchild);
        delete root;
    }
}
template<class T>               ///层序遍历
void BiTree<T>::LevelOrder(BiNode<T> *root)
{
    queue<BiNode<T> *>aqueue;
    if(root)///当根节点不为空
    {
        aqueue.push(root);
        while(!aqueue.empty())
        {
            root=aqueue.front();
            aqueue.pop();
            cout<<root->data;
            if(root->lchild) aqueue.push(root->lchild);
            if(root->rchild)  aqueue.push(root->rchild);
        }

    }


}
int main()///在主函数中测试前、中、后、层序遍历
{
    char s;
    while (true)
    {

        BiTree<char> a;
        cin>>s;
        a.PreOrder();

        cout << endl;
        a.InOrder();
        cout << endl;
        a.PostOrder();
        cout << endl;
        a.LevelOrder();
        cout<<endl;

    }
    return 0;
}

非递归实现二叉树的前、中、后序访问并测试代码:

#include<bits/stdc++.h>
using namespace std;
template <class T>
struct BiNode
{
	T  data;
	BiNode<T> *lchild, *rchild;
};
template <class T>
class BiTree
{
public:
	BiTree(){Creat(root);}
	~BiTree(){Release(root);}
	void PreOrder() { PreOrder(root); }
	void InOrder() { InOrder(root); }
	void PostOrder() { PostOrder(root);}
	void LevelOrder(){LevelOrder(root);}
private:
	BiNode<T> *root;
	void Creat(BiNode<T> *& root);
	void Release(BiNode<T> *root);
	void PreOrder(BiNode<T> *root);
	void InOrder(BiNode<T> *root);
	void PostOrder(BiNode<T> *root);
	void LevelOrder(BiNode<T> *root);
};

template<class T>          ///建立二叉树
void BiTree<T>::Creat(BiNode<T>*&root)
{
	T ch;
	cin >> ch;
	if (ch == '#') root = NULL;
	else {
		root = new BiNode<T>;
		root->data = ch;
		Creat(root->lchild);
		Creat(root->rchild);
	}

}
/*非递归实现前序遍历时,当根节点和栈都不为空时,先访问当前的根节点,倘若不为空,输出当前节点的值将当前的
根节点入栈 ,继续遍历当前节点的左孩子,否则若栈不为空,将节点出栈,访问它的右孩子,直到根节点和栈都为空*/
template<class T>                      ///前序遍历
void BiTree<T>::PreOrder(BiNode<T> *root)
{
	stack<BiNode<T> *>astack;
	while(root||!astack.empty())
    {
        while(root)
        {
            cout<<root->data;
            astack.push(root);
            root=root->lchild;

        }
        if(!astack.empty())
        {
            root=astack.top();
            astack.pop();
            root=root->rchild;
        }

    }
}

template<class T>                      ///中序遍历
void BiTree<T>::InOrder(BiNode<T> *root)
{
     stack<BiNode<T>* >astack;
     while(root||!astack.empty())
     {
         while(root)
         {
             astack.push(root);
             root=root->lchild;
         }
         if(!astack.empty())
         {
             root=astack.top();
             cout<<root->data;
             astack.pop();
             root=root->rchild;
         }

     }
}
/*对于每个节点,都压入两遍,在循环体中,每次弹出一个节点赋给p,
如果p仍然等于栈的头结点,说明p的孩子们还没有被操作过,
应该把它的孩子们加入栈中,否则,访问p。也就是说,第一次弹出,
将p的孩子压入栈中,第二次弹出,访问p。*/
template<class T>                      ///后序遍历
void BiTree<T>::PostOrder(BiNode<T> *root)
{
     stack<BiNode<T>* >astack;
     BiNode<T> *p=root;
     astack.push(p);
     astack.push(p);
     while(!astack.empty())
     {

         p=astack.top();
         astack.pop();
         if(!astack.empty()&&p==astack.top())
         {

               if(p->rchild) astack.push(p->rchild), astack.push(p->rchild);
               if(p->lchild) astack.push(p->lchild), astack.push(p->lchild);
         }
         else
         {
             cout<<p->data;
         }
     }


}

template<class T>
void BiTree<T>::Release(BiNode<T>* root)
{
	if (root != NULL) {
		Release(root->lchild);
		Release(root->rchild);
		delete root;
	}
}
template<class T>               ///层序遍历
void BiTree<T>::LevelOrder(BiNode<T> *root)
{
    queue<BiNode<T> *>aqueue;
    if(root)///当根节点不为空
    {
        aqueue.push(root);
        while(!aqueue.empty())
        {
            root=aqueue.front();
            aqueue.pop();
            cout<<root->data;
            if(root->lchild) aqueue.push(root->lchild);
            if(root->rchild)  aqueue.push(root->rchild);
        }

    }


}
int main()
{
	char s;
	while (true)
	{

		BiTree<char> a;
		cin>>s;
		a.PreOrder();

		cout << endl;
        a.InOrder();
		cout << endl;
		a.PostOrder();
		cout << endl;
		a.LevelOrder();
		cout<<endl;

	}
	return 0;
}

 关于树的节点数、叶子节点数、高度、交换左右子树算法的实现及检验:

 

#include <bits/stdc++.h>
 using namespace std;
struct BiNode
{
    char data;
    BiNode *lchild,*rchild;
};
class BiTree
{
  public:
	     int number;
		 int leave; BiTree();
		 void PreOrder(){PreOrder(root);}
         void countNode(){countNode(root);}
         void countLeaf(){countLeaf(root);}
         int height(){return height(root);}
         void swapTree(){swapTree(root);}
private:
         BiNode *root; 
         BiNode *creat();
		 void PreOrder(BiNode *root);//前序遍历
		 void countNode(BiNode *root);
		 void countLeaf(BiNode *root);
		 int height(BiNode *root);
		 void swapTree(BiNode *root);
}; 
BiTree ::BiTree(){ root=creat(); }
BiNode * BiTree ::creat(){
	BiNode *root;
	char ch; cin>>ch;
	if (ch=='#') root=NULL;
	else {
		  root=new BiNode;
		  root->data=ch; root->lchild=creat();
		  root->rchild= creat(); } 
		  return root;
}
void BiTree::countNode(BiNode *root) {///统计节点数
	if (root ==NULL) return;
	else {
		    countNode(root->lchild);
			number++;
			countNode(root->rchild); 
			
        }
}
void BiTree::countLeaf(BiNode *root) {///统计叶子节点数
	if (root ==NULL) return;
	 else {
		    if(root->lchild==NULL&&root->rchild==NULL){ leave++; }
			  countLeaf(root->lchild); 
			  countLeaf(root->rchild); 
            }
}
 int BiTree::height(BiNode *root) {///统计树的高度
	   int lheight=0,rheight=0;
	   if(root){ lheight=height(root->lchild);
	             rheight=height(root->rchild);
				 if(lheight>rheight) return lheight+1;
				 else return rheight+1;
                }
        else  return 0;
 }
void BiTree::swapTree(BiNode *root)///左后树交换
{
	BiNode *temp;
	if(root){ temp=root->lchild;
	root->lchild=root->rchild;
	root->rchild=temp;
	swapTree(root->lchild);
	swapTree(root->rchild); 
	}
}
void BiTree::PreOrder(BiNode *root)
{
	if (root ==NULL) return;
	else { cout<<root->data;
	PreOrder(root->lchild);
	PreOrder(root->rchild); }
}
int main() {
	char ch='Y';
	while(ch=='Y'){
		BiTree bt;
		bt.number=0;
		bt.countNode();
		cout<<bt.number<<endl;
		bt.leave=0; bt.countLeaf();
		cout<<bt.leave<<endl;
		int h=0; h=bt.height();
		cout<<h<<endl; bt.swapTree();
		bt.PreOrder();
		cout<<endl; cin>>ch; }
	return 0;
}

 线索二叉树的实现:

enum flag{Child,Thread};

template<class T>
struct ThrNode
{
    T data;
    ThrNode<T> *lchild,*rchild;
    flag ltag,rtag;
};
template<class T>
class InThrBiTree{
   public:
       InThrBiTree(){this->root=Creat();ThrBiTree(root);}
       ~InThrBiTree();
        ThrNode<T>*Next(ThrNode<T> *p);
        void InOrder(ThrNode<T> *root);
        ThrNode<T> *pre;
   private:
        ThrNode<T> *root;
        ThrNode<T> *  Creat();
        void ThrBiTree(ThrNode<T> *root);
};

template <class T>
ThrNode<T>* InThrBiTree<T>::Creat( ){
    ThrNode<T> *root;
    T ch;
    cout<<"请输入创建一棵二叉树的结点数据"<<endl;
    cin>>ch;
    if (ch=="#") root = NULL;
    else{
         root=new ThrNode<T>;
         root->data = ch;
         root->ltag = Child; root->rtag = Child;
         root->lchild = Creat( );
         root->rchild = Creat( );
    }
	return root;
}
template<class T>
void InThrBiTree<T>::ThrBiTree(ThrNode<T> *root)///递归实现线索二叉树
{
    if(root==NULL) return;
    else
    {
        if(!root->lchid)
        {
            root->lrag=Thread;
            root->lchild=pre;
        }
    }
    if(!root->rchild) root->rtag=Thread;
    if(!pre)
    {
        if(pre->rtag==Thread)
        {
            pre->rchild=root;
        }
    }
    pre==root;
    ThrBiTree(root->rchild);
}
template<class T>
ThrNode<T>* InThrBiTree<T>::Next(ThrNode<T> *p)
{
    ThrNode<T>*q;///要查找的P的后继
    if(p->rtag==Thread) q=p->rchild;
    else
    {
        q=p->rchild;
        while(q->ltag==Child)
        {
            q=q->lchild;
        }
    }
    return q;
}
template<class T>
void InThrBiTree<T>::InOrder(ThrNode<T> *root)
{
    ThrNode<T> *p=root;
    if(root==NULL) return;
    while(p->ltag==Child) {p=p->lchild;cout<<p->data<<" ";}

    while(!p->rchild)
    {
        p=Next(p);
        cout<<p->data<<" ";
    }
    cout<<endl;
}

 

posted on 2019-04-09 09:21  Sean521  阅读(213)  评论(0编辑  收藏  举报

导航