二叉树遍历及实现

几个二叉树的性质首先要知道:每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。 1、非空二叉树的第n层上至多有2^(n-1)个元素。 2、深度为h的二叉树至多有2^h-1个结点。 满二叉树:所有终端都在同一层次,且非终端结点的度数为2。 在满二叉树中若其深度为h,则其所包含的结点数必为2^h-1。 完全二叉树:除了最大的层次即成为一颗满二叉树且层次最大那层所有的结点均向左靠齐,即集中在左面的位置上,不能有空位置。

一、存储结构

顺序存储:

数据结构存在一块固定的数组中。

#define LENGTH 100
typedef char datatype;
typedef struct node{
    datatype data;
    int lchild,rchild;
    int parent;
}Node;

Node tree[LENGTH];
int length;
int root;

虽然在遍历速度上有一定的优势,但因所占空间比较大,是非主流二叉树。二叉树通常以链式存储。

链式存储:

typedef char datatype;

typedef struct BinNode{
    datatype data;
    struct BinNode* lchild;
    struct BinNode* rchild;
}BinNode;

typedef BinNode* bintree;          //bintree本身是个指向结点的指针

二、二叉树的遍历

遍历即将树的所有结点访问且仅访问一次。按照根节点位置的不同分为前序遍历,中序遍历,后序遍历。

前序遍历:根节点->左子树->右子树

中序遍历:左子树->根节点->右子树

后序遍历:左子树->右子树->根节点

例如:求下面树的三种遍历

前序遍历:abdefgc

中序遍历:debgfac

后序遍历:edgfbca

三、遍历的实现

递归实现(以前序遍历为例,其他的只是输出的位置稍有不同)

void preorder(bintree t){
    if(t){
        printf("%c ",t->data);
        preorder(t->lchild);
        preorder(t->rchild);
    }
}

非递归的实现

因为当遍历过根节点之后还要回来,所以必须将其存起来。考虑到后进先出的特点,选用栈存储。数量确定,以顺序栈存储。

#define SIZE 100
typedef struct seqstack{
    bintree data[SIZE];
    int tag[SIZE];   //为后续遍历准备的
    int top;     //top为数组的下标
}seqstack;

void push(seqstack *s,bintree t){

    if(s->top == SIZE){
        printf("the stack is full\n");
    }else{
        s->top++;
        s->data[s->top]=t;
    }
}

bintree pop(seqstack *s){
    if(s->top == -1){
        return NULL;
    }else{
        s->top--;
        return s->data[s->top+1];
    }
}

先序遍历

void preorder_dev(bintree t){
    seqstack s;
    s.top = -1;     //因为top在这里表示了数组中的位置,所以空为-1
    if(!t){
        printf("the tree is empty\n");
    }else{
        while(t || s.stop != -1){
            while(t){    //只要结点不为空就应该入栈保存,与其左右结点无关
                  printf("%c ",t->data);
                push(&s,t);
                t= t->lchild;
            }
        }
}

中序遍历

void midorder(bintree t){
    seqstack s;
    s.top = -1;
    if(!t){
        printf("the tree is empty!\n");
    }else{
        while(t ||s.top != -1){
            while(t){
                push(&s,t);
                t= t->lchild;
            }
            t=pop(&s);
            printf("%c ",t->data);
            t=t->rchild;
        }
    }
}

后序遍历

因为后序遍历最后还要要访问根结点一次,所以要访问根结点两次。采取夹标志位的方法解决这个问题。

这段代码非常纠结,对自己有信心的朋友可以尝试独立写一下。反正我是写了很长时间。逻辑不难,我画了一张逻辑图:

void postorder_dev(bintree t){
    seqstack s;
    s.top = -1;
    if(!t){
        printf("the tree is empty!\n");
    }else{
        while(t || s.top != -1){    //栈空了的同时t也为空。
            while(t){
                push(&s,t);
                s.tag[s.top] = 0;   //设置访问标记,0为第一次访问,1为第二次访问
                t= t->lchild;
            }
            if(s.tag[s.top] == 0){  //第一次访问时,转向同层右结点
                t= s.data[s.top];   //左走到底时t是为空的,必须有这步!
                s.tag[s.top]=1;
                t=t->rchild;
            }else {
                while (s.tag[s.top] == 1){ //找到栈中下一个第一次访问的结点,退出循环时并没有pop所以为其左子结点
                    t = pop(&s);
                    printf("%c ",t->data);
                }
                t = NULL; //必须将t置空。跳过向左走,直接向右走
            }
        }
    }
}

层次遍历

队列定义:

#define MAX 1000

typedef struct seqqueue{
    bintree data[MAX];
    int front;
    int rear;
}seqqueue;

void enter(seqqueue *q,bintree t){
    if(q->rear == MAX){
        printf("the queue is full!\n");
    }else{
        q->data[q->rear] = t;
        q->rear++;
    }
}

bintree del(seqqueue *q){
    if(q->front == q->rear){
        return NULL;
    }else{
        q->front++;
        return q->data[q->front-1];
    }
}

实现

void level_tree(bintree t){
    seqqueue q;
    bintree temp;
    q.front = q.rear = 0;
    if(!t){
        printf("the tree is empty\n");
        return ;
    }
    enter(&q,t);
    while(q.front != q.rear){
        t=del(&q);
        printf("%c ",t->data);
        if(t->lchild){
            enter(&q,t->lchild);
        }
        if(t->rchild){
            enter(&q,t->rchild);
        }
    }
}
时间: 2024-10-12 08:34:51

二叉树遍历及实现的相关文章

数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] 树 数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树 二叉树的创建,关系建立 二叉树的创建,关系建立2 三叉链表法 双亲链表: 二叉树的遍历 遍历的分析PPT 计算二叉树中叶子节点的数目:使用全局变量计数器 计算二叉树中叶子节点的数目:不使用全局变量计数器 无论是先序遍历,中序遍历,后序遍历,求叶子的数字都不变;因为本质都是一样的,任何一个节点都会遍历3趟 求二叉树的高度 二叉树的拷

二叉树遍历递归与非递归实现

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 二叉树遍历是二叉树中非常基础的部分,也是学习二叉树必须熟练掌握的部分,下面我们先给出二叉树三种遍历方式的定义,并通过举例来说明二叉树遍历的过程. 二叉树的遍历分为:前序遍历(也叫先序遍历).中序遍历.后序遍历.所谓前.中.后都是根据当前子树根结点相对左右孩子的位置而言,也就是说: 前序遍历:根结点在前,即:根 ----->左------->右: 中序遍历:根结点在中间,即:左------>根------>右: 后序遍历:根结点在最

算法之二叉树遍历

[代码示例] package com.wcs.java; import java.util.ArrayList; import java.util.List; public class BinaryTree { class TreeNode { public String data; //数据 public TreeNode leftNode; //左子树 public TreeNode rightNode; //右子树 public TreeNode(String data, TreeNode

morris算法-----高级二叉树遍历算法

在遍历儿叉树时,常常使用的是递归遍历,或者是借助于栈来迭代,在遍历过程中,每个节点仅访问一次,所以这样遍历的时间复杂度为O(n),空间复杂度为O(n),并且递归的算法易于理解和实现.在遍历过程中,递归遍历过程的空间复杂度却是O(n),就算是转换为使用栈空间迭代时间,还是没有改变算法对额外空间的需求,在学习数据结构课程时,还学习了线索二叉树,在线索二叉树中,使用线索来保存节点的前驱和后继的信息,而这些线索是利用了叶节点的空指针域来保存,所以知道了树种每个节点的前驱和后继的位置(指针)可以有效降低遍

D - 二叉树遍历(推荐)

二叉树遍历问题 Description Tree Recovery Little Valentine liked playing with binary trees very much. Her favorite game was constructing randomly looking binary trees with capital letters in the nodes. This is an example of one of her creations: D / / B E /

poj2255 (二叉树遍历)

poj2255 二叉树遍历 Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description Little Valentine liked playing with binary trees very much. Her favorite game was constructing randomly looking binary trees with capital letters in the

二叉树遍历 (递归算法)

二叉树遍历之递归算法 # include<iostream> # include<cstdio> using namespace std; struct Node { int data; Node *rchild,*lchild; }; void visit(int x) { printf("%d",x); } void Preorder(Node *T) { if(T==NULL) return ; visit(T->data); Preorder(T-

二叉树遍历 C#

二叉树遍历 C# 什么是二叉树 二叉树是每个节点最多有两个子树的树结构 (1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二 叉树. (2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树. (3)平衡二叉树——平衡二叉树又被称为AVL树,它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是

二叉树遍历-JAVA实现

二叉树遍历分为前序.中序.后序递归和非递归遍历.还有层序遍历. 1 //二叉树节点 2 public class BinaryTreeNode { 3 private int data; 4 private BinaryTreeNode left; 5 private BinaryTreeNode right; 6 7 public BinaryTreeNode() {} 8 9 public BinaryTreeNode(int data, BinaryTreeNode left, Binar

二叉树遍历 - 数据结构

1. 二叉树遍历 1.1 遍历算法: 1.先序遍历的递归算法定义: 若二叉树非空,则依次执行如下操作: (1) 访问根结点: (2) 遍历左子树: (3) 遍历右子树. 2.中序遍历的递归算法定义: 若二叉树非空,则依次执行如下操作: (1)遍历左子树: (2)访问根结点: (3)遍历右子树. 3.后序遍历得递归算法定义: 若二叉树非空,则依次执行如下操作: (1)遍历左子树: (2)遍历右子树: (3)访问根结点. 4.层次遍历:层序遍历(level traversal)二叉树的操作定义为: