前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(较为详细)树的遍历方式一览(附完整源码可在VScode与cb运行)

(较为详细)树的遍历方式一览(附完整源码可在VScode与cb运行)

作者头像
glm233
发布2020-09-28 11:04:55
3770
发布2020-09-28 11:04:55
举报
文章被收录于专栏:glm的全栈学习之路

1.二叉链表求树的层次遍历

层次遍历需要用到队列,为加深理解,这里手敲队列

代码语言:javascript
复制
#include <stdio.h>
#include<malloc.h>
#define MAX 100

typedef int Element;

typedef struct tree
{
	Element ch;
	struct tree *left;
	struct tree *right;
}Tree;

typedef struct queue
{
	Tree *a[MAX];
    int front;
	int rear;
}Queue;

Queue Qu;

void Init();
int InsertQueue(Element ch);
Tree *DeleteQueue();

void CreateTree(Tree **r);
void TransLevele(Tree *r);
void PrintTree(Tree *r);


int main()
{
	
	Tree *r=NULL;
	CreateTree(&r);
	PrintTree(r);
	printf("\n");
    TransLevele(r);
	while(1)getchar();
	return 0;
}

void Init()
{
	int i=0;
	for (i=0; i<MAX; i++)
	{
		Qu.a[i] = NULL;
	}
	Qu.front = 0;
	Qu.rear = 0;
}
int InsertQueue(Tree *r)
{
    if ( (Qu.rear+1)%MAX == Qu.front)
    {
		printf("Queue full!");
		return 0;
    }
    Qu.a[Qu.rear] = r;
	Qu.rear = (Qu.rear+1)%MAX;
    return 1;
}
Tree *DeleteQueue()
{
    if (Qu.front == Qu.rear)
    {
		printf("\nQueue empty");
		return NULL;
    }
	Tree *t=NULL;
	t = Qu.a[Qu.front];
	Qu.front = (Qu.front+1)%MAX;
	return t;
}
void CreateTree(Tree **r)
{
    Element ch;
	ch=getchar();
	if (ch=='#')
	{
		(*r)=NULL;
		return ;
	}
	*r = (Tree *)malloc(sizeof(Tree));
    (*r)->ch = ch;
	CreateTree(&((*r)->left));
	CreateTree(&((*r)->right));
}
void PrintTree(Tree *r)
{
    if (r==NULL)
    {
		return ;
    }
	printf("%c",r->ch);
	PrintTree(r->left);
	PrintTree(r->right);
}
void TransLevele(Tree *r)
{
    if (r==NULL)
    {
		return ;
    }
	printf("%c",r->ch);
	if (r->left != NULL)
	{
       InsertQueue(r->left);
	}
	if (r->right != NULL)
	{
	   InsertQueue(r->right);
	}

	Tree *t = DeleteQueue();
	TransLevele(t);
}

2.带双亲域遍历,只能支持前后序遍历(原因很简单,因为该结构中不存在左右儿子结点)

代码语言:javascript
复制
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<algorithm>
#include<iostream>
#define TElemType char
#define Max 100
using namespace std;
typedef struct TNode
{
	TElemType data;
	int parent;
}TNode;
typedef struct Tree
{

	TNode parent[Max];
	int NodeNum;

}Tree;

void InitTree(Tree &T)
{
	for (int i=0;i<Max;i++)
	{
		T.parent[i].data = '#';
		T.parent[i].parent = -1;
	}
	T.NodeNum = 0;
}
//插入树的结点 参数:树T,结点node 作用:在双亲数组中插入结点,增加树的结点值
bool InsertNode(Tree &T, TElemType node)
{

	if (node != '#')
	{
		T.parent[T.NodeNum++].data = node;//插入到双亲数组中
		return true;
	}
	return false;
}
//插入双亲数组的双亲域 参数:树T ,结点node1,结点node2
//作用:使双亲数组中,node2对应的双亲域为node1的下标
bool InsertParent(Tree &T, TElemType node1, TElemType node2)
{
	int place1, place2;
	place1 = -1;place2 = -1;
	for (int i=0;i<T.NodeNum;i++)//查找两点是否存在
	{
		if (node1 == T.parent[i].data)place1 = i;
		if (node2 == T.parent[i].data)place2 = i;
	}
	if (place1 != -1 && place2 != -1)//两点均存在
	{
		T.parent[place2].parent = place1;
		return true;
	}
	return false;
}

void PreOrder(Tree T,int i)
{
	if (T.NodeNum != 0)
	{
		cout << T.parent[i].data << " ";
		for(int j=0;j<T.NodeNum;j++)
		{
		  if(T.parent[j].parent==i)
		  PreOrder(T,j);
		}
	}
}

void CreateTree(Tree &T)
{
	int nodenum = 0;
	int parent;
	TElemType node,node1,node2;
	printf("请输入树的结点个数:");
	cin >> nodenum;
	parent = nodenum - 1;
	printf("请输入树的结点名称(空格隔开):");
	while (nodenum--)
	{
		cin >> node;
		InsertNode(T,node);
	}
	printf("请输入树的结点间的双亲关系(一对为一双亲关系,A B表示A为B的双亲):\n");
	while (parent--)
	{
		cin >> node1>>node2;
		InsertParent(T,node1,node2);
	}
	printf("\n");
}


int main()
{
	Tree T;
	InitTree(T);
	CreateTree(T);
	PreOrder(T,0);
	while(1)getchar();
	return 0;
}

3.树的递归遍历(最简短)

代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>

#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define TRUE 1
#define FALSE 0
#define SIZEINIT 10
#define INCRESIZE 5

typedef int Status;
typedef char TElemType;

typedef struct node{
	TElemType data;
	struct node *lchild,*rchild;
}BiTNode,*BiTree;

//前序创建二叉树
void CreateBiTree(BiTree &T){
	char ch;
	scanf("%c",&ch);
	if(ch=='#'){
		T = NULL;
	}else{
		T = (BiTree)malloc(sizeof(struct node));
		T->data = ch;
		CreateBiTree(T->lchild);
		CreateBiTree(T->rchild);
	}
}

//前序遍历
Status PreOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
	if(T){
		if(Visit(T->data)){
			if(PreOrderTraverse(T->lchild,Visit)){
				if(PreOrderTraverse(T->rchild,Visit)) return OK;
			}
		}
		return ERROR;
	}
	return OK;
}

//中序遍历
Status InOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
	if(T){
		if(InOrderTraverse(T->lchild,Visit)){
			if(Visit(T->data)){
				if(InOrderTraverse(T->rchild,Visit)) return OK;
			}
		}
		return ERROR;
	}
	return OK;
}

//后序遍历
Status PostOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
	if(T){
		if(PostOrderTraverse(T->lchild,Visit)){
			if(PostOrderTraverse(T->rchild,Visit)){
				if(Visit(T->data)) return OK;
			}
		}
		return ERROR;
	}
	return OK;
}

//访问函数
Status Visit(TElemType e){
	printf("%c",e);
	return OK;
}

int main(){
	BiTree T = NULL;
	printf("请前序创建第一棵树(空位置用'#'来代替)\n");
	CreateBiTree(T);
	printf("\n二叉树前序遍历的结果\n");
	PreOrderTraverse(T,Visit);
	printf("\n二叉树中序遍历的结果\n");
	InOrderTraverse(T,Visit);
	printf("\n二叉树后序遍历的结果\n");
	PostOrderTraverse(T,Visit);
	printf("\n");
    while(1)getchar();
    return 0;
}
//AB#D##CE###

4.先序建立二叉链表求后序遍历序列

思路:初始结点标记为零 对于某个结点先遍历完其左子树(不断压左子树结点进栈),然后结点标记++,表示其左子树全部遍历,之后如果无右子树直接出栈输出,否则遍历其右子树同时将其标记++,对于标记为2的结点马上输出并出栈

代码语言:javascript
复制
#include <iostream>
#include<stack>
#include<malloc.h>
using namespace std;

typedef struct node {
    char  data;
    struct node* left = NULL;
    struct node* right = NULL;
    int times = 0;
}node,*tree;
inline void initial(tree &T)
{
    char ch;
    cin>>ch;
    if(ch=='#')
    {
        T=NULL;
        return ;
    }
    else
    {
        T=(tree)malloc(sizeof(node));
        T->data=ch;
        initial(T->left);
        initial(T->right);
    }
}
inline void display(tree &T)
{
    if(!T)return ;
    cout<<T->data<<endl;
    display(T->left);
    display(T->right);
}
int main()
{

    tree T=(tree)malloc(sizeof(node));
    initial(T);
    cout<<"begin"<<endl;
    display(T);
    cout<<"begin"<<endl;
    stack<tree> s;
    tree p=T;
    while (p != nullptr || !s.empty()) {
        if (p == nullptr) {
            p = s.top();
            s.pop();
            p->times++;
        }
        else {
            if (p->times == 2) {
                cout << p->data << " ";
                p = nullptr;
            }
            else if(p->times==1) {
                s.push(p);
                p = p->right;
            }
            else {
                s.push(p);
                p = p->left;
            }
        }
    }
    return 0;
}

5.线索二叉树中序遍历

主要思想是将其空节点改造为前驱指针和后继指针

代码语言:javascript
复制
#include <stdlib.h>
#include <stdio.h>
#define elemtype char
#define Status int
const int ERROR = 0; 
const int OK = 1;
typedef enum pointer{
	tlink,thread
}fingurePointer;
 
typedef struct  binNode{
	struct  binNode *lchild,*rchild;
	fingurePointer ltag,rtag;
	elemtype data;	
}thrNode,*orderTree; 
 
orderTree pre;
 
 

 
/*前序遍历的递归创建树*/
void CreateBiTree(orderTree *T)
  {
      char ch;
      scanf("%c",&ch);
      if(ch=='#')
          *T=NULL;
      else
     {
         *T=(struct binNode *)malloc(sizeof(thrNode));
         if(!*T)
			exit(-1);
			(*T)->data=ch;
			(*T)->ltag = tlink;
			(*T)->rtag = tlink;
			CreateBiTree(&(*T)->lchild);
			CreateBiTree(&(*T)->rchild);
      }
 }
 
void visit(orderTree node)
{
	orderTree p;
	p = node;
	if(p!=NULL)
	{
	visit(p->lchild);
	printf("%d  %c   %d\n",p->ltag,p->data,p->rtag);
	visit(p->rchild);
	}
}

 
 
 
//中序线索二叉树 
void inThreading(orderTree node)
{
	if(node)
	{
		inThreading(node->lchild);//线索化左子树 
		
		if(!node->lchild){//左子树为空,改变ltag,指定lchild为pre 
			node->ltag = thread;
			node->lchild = pre;
		}
		if(!pre->rchild)//右子树为空,改变rtag,指定pre的 rchild 
		{
			pre->rtag = thread;
			pre->rchild = node;	
		}
		pre= node; 
		inThreading(node->rchild);		
	}
}
 
 
 
Status InOrderThreading(orderTree &head,orderTree root)
{
	
	if(!(head=(struct binNode *)malloc(sizeof(struct binNode))))
		return ERROR;
	/*头结点左孩子指向根节点,右节点指向直接前驱*/ 
	head->ltag = tlink; head->rtag = thread;
	head->rchild = head;//右指针回指
	
	if(!root) head->lchild = head;
	 else{
	 	head->lchild = root;
		 pre = head;	
		 inThreading(root);
		 pre->rchild = head;
		 pre->rtag = thread;
		 head->rchild = pre;
	 }
	 return OK;
}
 
void visitNode(orderTree p)
{
	if(p!=NULL)
	printf("%c ",p->data);	
} 
 
Status InOderTranverse(orderTree head)
{
	orderTree p;
	p = head->lchild;//p指向根节点
	
	while(p!=head)
	{
		//左子树 
		while(p->ltag==tlink)
			p = p->lchild;
		visitNode(p);
		//右子树 
		while(p->rtag ==thread&&p->rchild!=head)
		{
			p = p->rchild;
			visitNode(p);	
		}
		p = p->rchild;
	} 
	 return OK;
}
 
int main() 
{
	orderTree root;
	CreateBiTree(&root);  
	orderTree head;
	Status x =	InOrderThreading(head,root);
	InOderTranverse(head);
    while(1)getchar();
	
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/11/08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档