数据结构(二十四)二叉树的链式存储结构(二叉链表)

  一、二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域,称这样的链表叫做二叉链表。

  二、结点结构包括:lchild左孩子指针域、data数据域和rchild右孩子指针域。

  三、二叉链表的C语言代码实现:

#include "string.h"
#include "stdio.h"    
#include "stdlib.h"   
#include "io.h"  
#include "math.h"  
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 100 /* 存储空间初始分配量 */

typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */

/* 用于构造二叉树********************************** */
int index=1;
typedef char String[24]; /*  0号单元存放串的长度 */
String str;

Status StrAssign(String T,char *chars)
{ 
    int i;
    if(strlen(chars)>MAXSIZE)
        return ERROR;
    else
    {
        T[0]=strlen(chars);
        for(i=1;i<=T[0];i++)
            T[i]=*(chars+i-1);
        return OK;
    }
}
/* ************************************************ */

typedef char TElemType;
TElemType Nil=' '; /* 字符型以空格符为空 */

Status visit(TElemType e)
{
    printf("%c ",e);
    return OK;
}

typedef struct BiTNode  /* 结点结构 */
{
   TElemType data;        /* 结点数据 */
   struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
}BiTNode,*BiTree;


/* 构造空二叉树T */
Status InitBiTree(BiTree *T)
{ 
    *T=NULL;
    return OK;
}

/* 初始条件: 二叉树T存在。操作结果: 销毁二叉树T */
void DestroyBiTree(BiTree *T)
{ 
    if(*T) 
    {
        if((*T)->lchild) /* 有左孩子 */
            DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */
        if((*T)->rchild) /* 有右孩子 */
            DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */
        free(*T); /* 释放根结点 */
        *T=NULL; /* 空指针赋0 */
    }
}

/* 按前序输入二叉树中结点的值(一个字符) */
/* #表示空树,构造二叉链表表示二叉树T。 */
void CreateBiTree(BiTree *T)
{ 
    TElemType ch;
    
    /* scanf("%c",&ch); */
    ch=str[index++];

    if(ch=='#') 
        *T=NULL;
    else
    {
        *T=(BiTree)malloc(sizeof(BiTNode));
        if(!*T)
            exit(OVERFLOW);
        (*T)->data=ch; /* 生成根结点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
 }

/* 初始条件: 二叉树T存在 */
/* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
Status BiTreeEmpty(BiTree T)
{ 
    if(T)
        return FALSE;
    else
        return TRUE;
}

#define ClearBiTree DestroyBiTree

/* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
int BiTreeDepth(BiTree T)
{
    int i,j;
    if(!T)
        return 0;
    if(T->lchild)
        i=BiTreeDepth(T->lchild);
    else
        i=0;
    if(T->rchild)
        j=BiTreeDepth(T->rchild);
    else
        j=0;
    return i>j?i+1:j+1;
}

/* 初始条件: 二叉树T存在。操作结果: 返回T的根 */
TElemType Root(BiTree T)
{ 
    if(BiTreeEmpty(T))
        return Nil;
    else
        return T->data;
}

/* 初始条件: 二叉树T存在,p指向T中某个结点 */
/* 操作结果: 返回p所指结点的值 */
TElemType Value(BiTree p)
{
    return p->data;
}

/* 给p所指结点赋值为value */
void Assign(BiTree p,TElemType value)
{
    p->data=value;
}

/* 初始条件: 二叉树T存在 */
/* 操作结果: 前序递归遍历T */
void PreOrderTraverse(BiTree T)
{ 
    if(T==NULL)
        return;
    printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
    PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */
    PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */
}

/* 初始条件: 二叉树T存在 */
/* 操作结果: 中序递归遍历T */
void InOrderTraverse(BiTree T)
{ 
    if(T==NULL)
        return;
    InOrderTraverse(T->lchild); /* 中序遍历左子树 */
    printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
    InOrderTraverse(T->rchild); /* 最后中序遍历右子树 */
}

/* 初始条件: 二叉树T存在 */
/* 操作结果: 后序递归遍历T */
void PostOrderTraverse(BiTree T)
{
    if(T==NULL)
        return;
    PostOrderTraverse(T->lchild); /* 先后序遍历左子树  */
    PostOrderTraverse(T->rchild); /* 再后序遍历右子树  */
    printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
}


int main()
{
    int i;
    BiTree T;
    TElemType e1;
    InitBiTree(&T);

    
    StrAssign(str,"ABDH#K###E##CFI###G#J##");

    CreateBiTree(&T);

    printf("构造空二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
    e1=Root(T);
    printf("二叉树的根为: %c\n",e1);

    printf("\n前序遍历二叉树:");
    PreOrderTraverse(T);
    printf("\n中序遍历二叉树:");
    InOrderTraverse(T);
    printf("\n后序遍历二叉树:");
    PostOrderTraverse(T);
    ClearBiTree(&T);
    printf("\n清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
    i=Root(T);
    if(!i)
        printf("树空,无根\n");
    
    return 0;
}



输出为:
构造空二叉树后,树空否?0(1:是 0:否) 树的深度=5
二叉树的根为: A

前序遍历二叉树:ABDHKECFIGJ
中序遍历二叉树:HKDBEAIFCGJ
后序遍历二叉树:KHDEBIFJGCA
清除二叉树后,树空否?1(1:是 0:否) 树的深度=0

  四、二叉链表的Java语言代码实现:

  • 二叉链表结点类:
package bigjun.iplab.linkBiTree;
/**
 * 二叉树的结点类
 */
public class BiTreeNode {
    
    public Object data;                 // 结点的数据域
    public BiTreeNode lchild, rchild;   // 左孩子和右孩子域
    
    // 构造方法1:构造一个空结点
    public BiTreeNode() {
    }
    
    // 构造方法2:构造没有左右孩子的结点
    public BiTreeNode(Object data) {
        this(data, null, null);
    }
    
    // 构造方法3:构造一棵数据域和左、右孩子域都不为空的二叉树
    public BiTreeNode(Object data, BiTreeNode lchild, BiTreeNode rchild) {
        this.data = data;
        this.lchild = lchild;
        this.rchild = rchild;
    }

}
  • 二叉链表接口类:
package bigjun.iplab.linkBiTree;

public interface LinkBiTreeINF {
    
    // 前序递归遍历算法
    public void preOrderTraverse(BiTreeNode T);
    // 中序递归遍历算法
    public void inOrderTraverse(BiTreeNode T);
    // 后序递归遍历算法
    public void postOrderTraverse(BiTreeNode T);
    // 前序非递归遍历算法
    public void preOrderTraverse() throws Exception;
    // 后序非递归遍历算法
    public void inOrderTraverse() throws Exception;
    // 中序非递归遍历算法
    public void postOrderTraverse() throws Exception;
    // 层序非递归遍历算法
    public void levelOrderTraverse() throws Exception;
    // (基于前序递归遍历算法) 在二叉树中查找值为x的结点,若找到,则返回该结点;否则,返回null
    public BiTreeNode searchBTNode(BiTreeNode T, Object x);
    // (基于前序递归遍历算法) 统计二叉树中结点的个数并返回
    public int countBTNode(BiTreeNode T);
    // (基于后序递归遍历算法) 求二叉树的深度
    public int getBTDepth(BiTreeNode T);
    // (基于前序递归遍历算法) 判断两棵二叉树是否相等,若相等,返回true;否则,返回false
    public boolean isEqual(BiTreeNode T1, BiTreeNode T2);
    // 根据二叉链表的定义即基本的构造方法创建一棵二叉树
    public LinkBiTree createLinkBiTreeByDefinition();
    // 根据前序遍历序列和中序遍历序列建立一棵二叉树
    public LinkBiTree createBiTreeByPreAndInOrder(String preOrder, String inOrder, int preIndex, int inIndex, int count);
    // 根据标明空子树的先序遍历序列建立一棵二叉树
    public LinkBiTree creataBiTreeByPreHasNullSign(String preStr);
    // 根据完全二叉树的顺序存储结构建立一棵链式存储的二叉树
    public LinkBiTree createBiTreeBySeqBiTree(String seqBiTree, int index);
    
}
  • 二叉链表实现类:
package bigjun.iplab.linkBiTree;

import bigjun.iplab.linkQueue.LinkQueue;
import bigjun.iplab.linkStack.LinkStack;
/**
 * 二叉树的链式存储结构-二叉链表存储结构
 */
public class LinkBiTree implements LinkBiTreeINF{
    
    private BiTreeNode root;
    
    // 构造方法1: 构造一棵空树
    public LinkBiTree() {
        this.root = null;
    }
    
    // 构造方法2: 构造一棵非空树
    public LinkBiTree(BiTreeNode root) {
        this.root = root;
    }
    
    // 构造方法3:由前序遍历序列和中序遍历序列建立一棵二叉树
    public LinkBiTree(String preOrder, String inOrder, int preIndex, int inIndex, int count) {
        // 如果前序和中序遍历序列不为空
        if (count > 0) {
            // 取前序遍历序列的第一个结点作为根结点
            char rChar = preOrder.charAt(preIndex);
            int i = 0;
            // 确定根结点在中序遍历序列的第i(从0开始)个位置
            for ( ; i < count; i++) {
                if (rChar == inOrder.charAt(i + inIndex)) {
                    break;
                }
            }
            // 创建根结点对应的二叉树链式存储结构的结点
            root = new BiTreeNode(rChar);
            // 确定左子树的根结点
            root.lchild = new LinkBiTree(preOrder, inOrder, preIndex + 1, inIndex, i).root;
            // 确定右子树的根结点
            root.rchild = new LinkBiTree(preOrder, inOrder, preIndex + i + 1, inIndex + i + 1, count - i - 1).root;
        }
    }
    
    // 构造方法4:由标明空子树的前序遍历序列建立一棵二叉树
    // static修饰的变量叫静态变量,JVM只分配一次内存,在对象之间共享值时要用static修饰
    private static int index = 0;// 这里要注意的是index要加staic关键字,否则每次new LinkBiTree(preStr)出新对象的时候index都是0,那样就会陷入死递归
    public LinkBiTree(String preStr) {
        char c = preStr.charAt(index++);
        if (c != '#') {
            root = new BiTreeNode(c);
            root.lchild = new LinkBiTree(preStr).root;
            root.rchild = new LinkBiTree(preStr).root;
        } else 
            root = null;
    }
    
    
    // 前序递归遍历算法
    public void preOrderTraverse(BiTreeNode T) {
        if (T != null) {
            System.out.print(T.data);
            preOrderTraverse(T.lchild);
            preOrderTraverse(T.rchild);
        }
    }
    
    // 中序递归遍历算法
    public void inOrderTraverse(BiTreeNode T) {
        if (T != null) {
            inOrderTraverse(T.lchild);
            System.out.print(T.data);
            inOrderTraverse(T.rchild);
        }
    }
    
    // 后序递归遍历算法
    public void postOrderTraverse(BiTreeNode T) {
        if (T != null) {
            postOrderTraverse(T.lchild);
            postOrderTraverse(T.rchild);
            System.out.print(T.data);
        }
    }
    
    // 前序非递归遍历算法
    public void preOrderTraverse() throws Exception {
        BiTreeNode T = root;
        if (T != null) {
            LinkStack stack = new LinkStack();                // 构造栈对象
            stack.stackPush(T);                                // 根结点前入栈
            while (!stack.isStackEmpty()) {                    // 栈不为空时
                T = (BiTreeNode) stack.stackPop();
                System.out.print(T.data);                     // 访问结点
                while (T != null) {
                    if (T.lchild != null) 
                        System.out.print(T.lchild.data);    // 访问结点的非空左孩子
                    if (T.rchild != null) 
                        stack.stackPush(T.rchild);            // 将结点的非空右孩子入栈
                    T = T.lchild;                            // 转换为原结点的非空左孩子
                }
            }
        }
    }
    
    // 中序非递归遍历算法
    public void inOrderTraverse() throws Exception{
        BiTreeNode T = root;
        if (T != null) {
            LinkStack stack = new LinkStack();            // 构造栈对象
            stack.stackPush(T);                            // 根结点前入栈 
            while (!stack.isStackEmpty()) {    
                while (stack.getTopElem() != null)      // 栈顶非空结点左孩子相继入栈
                    stack.stackPush(((BiTreeNode)stack.getTopElem()).lchild);
                stack.stackPop();                        // 如果没有左孩子或右孩子,将空的左孩子或右孩子出栈
                if (!stack.isStackEmpty()) {
                    T = (BiTreeNode) stack.stackPop();  // 栈顶结点出栈
                    System.out.print(T.data);            // 访问栈顶结点
                    stack.stackPush(T.rchild);            // 出栈的栈顶结点的右孩子入栈
                }
            }
        }
    }
    
    // 后序非递归遍历算法
    public void postOrderTraverse() throws Exception {
        BiTreeNode T = root;
        if (T != null) {
            LinkStack stack = new LinkStack();            // 构造栈对象
            stack.stackPush(T);                            // 根结点前入栈 
            Boolean flag;
            BiTreeNode p = null;
            while (!stack.isStackEmpty()) {    
                while (stack.getTopElem() != null)      // 栈顶非空结点左孩子相继入栈
                    stack.stackPush(((BiTreeNode)stack.getTopElem()).lchild);
                stack.stackPop();                        // 如果没有左孩子或右孩子,将空的左孩子或右孩子出栈
                while (!stack.isStackEmpty()) {
                    T = (BiTreeNode) stack.getTopElem();// 查看栈顶结点
                    if (T.rchild == null || T.rchild == p) { // 右孩子为空或右子树已经被访问
                        System.out.print(T.data);        // 访问栈顶结点
                        stack.stackPop();                // 移除栈顶结点
                        p = T;                            // p指向当被访问的结点
                        flag = true;                    // 设置已访问标记
                    } else {
                        stack.stackPush(T.rchild);        // 右孩子入栈
                        flag = false;                    // 设置未被访问标记
                    }
                    if (!flag)                             // 如果未被访问,则break
                        break;
                }
            }
        }
    }
    
    // 层序非递归遍历算法
    public void levelOrderTraverse() throws Exception {
        BiTreeNode T = root;
        if (T != null) {
            LinkQueue queue = new LinkQueue();            // 构造链队列
            queue.queueEnter(T);                        // 根结点入链队列
            while (! queue.isqueueEmpty()) {    
                T = (BiTreeNode) queue.queuePoll();        // 访问结点并出队列
                System.out.print(T.data);
                if (T.lchild != null)                     // 左孩子非空,入队列
                    queue.queueEnter(T.lchild);        
                if (T.rchild != null)                     // 右孩子非空,入队列
                    queue.queueEnter(T.rchild);
            }
        }
    }
    
    // (前序递归遍历算法)在二叉树中查找值为x的结点,若找到,则返回该结点;否则,返回null
    public BiTreeNode searchBTNode(BiTreeNode T, Object x) {
        if (T != null) {
            if (T.data == x) {                                    // 判断根结点
                return T;// 注意这里的return语句,只要查找到了就不用再继续往下查找了,不同于前序递归遍历算法。
            } else {
                // 查找左子树
                BiTreeNode lResult = searchBTNode(T.lchild, x);
                // 若在左子树中查找到x的结点,则返回该结点;否则,查找右子树并返回结果
                return lResult != null ? lResult : searchBTNode(T.rchild, x);
            }
        }
        return null;
    }
    
    // (前序递归遍历算法)统计二叉树中结点的个数并返回
    public int countBTNode(BiTreeNode T) {
        int count = 0;
        if (T != null) {
            ++count;
            count += countBTNode(T.lchild);
            count += countBTNode(T.rchild);
        }
        return count;
    }
    
    // (后序递归遍历算法) 求二叉树的深度
    public int getBTDepth(BiTreeNode T) {
        if (T != null) {
            int lDepth = getBTDepth(T.lchild);
            int rDepth = getBTDepth(T.rchild);
            return 1 + (lDepth > rDepth ? lDepth : rDepth);
        }
        return 0;
    }
    
    // (前序递归遍历算法) 判断两棵二叉树是否相等,若相等,返回true;否则,返回false
    public boolean isEqual(BiTreeNode T1, BiTreeNode T2) {
        if (T1 == null && T2 == null) 
            return true;
        if (T1 != null && T2 != null) {
            if (T1.data.equals(T2.data)) {
                if (isEqual(T1.lchild, T2.lchild)) {
                    if (isEqual(T1.rchild, T2.rchild)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
    // 采用构造方法2来构造二叉树1
    public LinkBiTree createLinkBiTreeByDefinition() {
        
        BiTreeNode k = new BiTreeNode('K');         // 要前定义孩子,因为程序是按前后顺序执行的
        BiTreeNode i = new BiTreeNode('I');
        BiTreeNode j = new BiTreeNode('J');
        BiTreeNode e = new BiTreeNode('E');
        
        BiTreeNode h = new BiTreeNode('H', null, k);
        BiTreeNode f = new BiTreeNode('F', i, null);
        BiTreeNode g = new BiTreeNode('G', null, j);
        BiTreeNode d = new BiTreeNode('D', h, null);
        
        BiTreeNode c = new BiTreeNode('C', f, g);
        BiTreeNode b = new BiTreeNode('B', d, e);
        BiTreeNode a = new BiTreeNode('A', b, c);
        
        return new LinkBiTree(a);
    }
    
    // 采用构造方法2来构造二叉树2(对比二叉树1来说,删除一个结点K)
    public LinkBiTree createLinkBiTreeByDefinitionSimilar() {
        
        BiTreeNode i = new BiTreeNode('I');
        BiTreeNode j = new BiTreeNode('J');
        BiTreeNode e = new BiTreeNode('E');
        
        BiTreeNode h = new BiTreeNode('H', null, null);
        BiTreeNode f = new BiTreeNode('F', i, null);
        BiTreeNode g = new BiTreeNode('G', null, j);
        BiTreeNode d = new BiTreeNode('D', h, null);
        
        BiTreeNode c = new BiTreeNode('C', f, g);
        BiTreeNode b = new BiTreeNode('B', d, e);
        BiTreeNode a = new BiTreeNode('A', b, c);
        
        return new LinkBiTree(a);
    }
    
    //由顺序存储的完全二叉树建立一棵连式存储的二叉树结点
    public BiTreeNode createBiTreeNodeBySeqBiTree(String seqBiTree, int index) {
        BiTreeNode root = null;                                    // 根结点
        if (index < seqBiTree.length()) {                        // 位置不超过字符串长度
            root = new BiTreeNode(seqBiTree.charAt(index));        // 从下标为0开始,建立二叉链表根结点
            root.lchild = createBiTreeNodeBySeqBiTree(seqBiTree, 2 * index + 1);// 建立左子树
            root.rchild = createBiTreeNodeBySeqBiTree(seqBiTree, 2 * index + 2);// 建立右子树
        }
        return root; // 返回二叉链表根结点对象
    }
    
    // 由顺序存储的完全二叉树建立一棵连式存储的二叉树
    public LinkBiTree createBiTreeBySeqBiTree(String seqBiTree, int index) {
        BiTreeNode root = createBiTreeNodeBySeqBiTree(seqBiTree, index);
        return new LinkBiTree(root);
    }
    
    // 由前序遍历序列和中序遍历序列建立一棵二叉树
    public LinkBiTree createBiTreeByPreAndInOrder(String preOrder, String inOrder, int preIndex, int inIndex, int count) {
        return new LinkBiTree(preOrder, inOrder, preIndex, inIndex, count);
    }
    
    // 由标明空子树的先序遍历序列建立一棵二叉树
    public LinkBiTree creataBiTreeByPreHasNullSign(String preStr) {
        return new LinkBiTree(preStr);
    }
    
    
    
    public static void main(String[] args) throws Exception {
        LinkBiTree linkBiTree = new LinkBiTree();            // 创建一棵空树
        LinkBiTree biTree = linkBiTree.createLinkBiTreeByDefinition();   // 调用创造方法创造根结点为a的二叉树
        BiTreeNode root = biTree.root;                       // 取得二叉树的根结点
        
        System.out.print("前序递归遍历算法得到的序列为:  ");
        linkBiTree.preOrderTraverse(root);                   
        System.out.println();
        System.out.print("中序递归遍历算法得到的序列为:  ");
        linkBiTree.inOrderTraverse(root);                    
        System.out.println();
        System.out.print("后序递归遍历算法得到的序列为:  ");
        linkBiTree.postOrderTraverse(root);                  
        System.out.println();
        
        System.out.print("前序非递归遍历算法得到的序列为: ");
        biTree.preOrderTraverse();                   
        System.out.println();
        System.out.print("中序非递归遍历算法得到的序列为: ");
        biTree.inOrderTraverse();                   
        System.out.println();
        System.out.print("后序非递归遍历算法得到的序列为: ");
        biTree.postOrderTraverse();                   
        System.out.println();
        System.out.print("层序非递归遍历算法得到的序列为: ");
        biTree.levelOrderTraverse();                   
        System.out.println();
        
        System.out.print("在二叉树中查找字符D返回的结点的数据域为:");
        System.out.println(linkBiTree.searchBTNode(root, 'D').data);
        System.out.print("在二叉树中查找字符W返回的结点为:");
        System.out.println(linkBiTree.searchBTNode(root, 'W'));
        
        System.out.println("二叉树中结点个数的统计结果为: " + linkBiTree.countBTNode(root));
        
        System.out.println("二叉树的深度为: " + linkBiTree.getBTDepth(root));
        
        LinkBiTree biTreeSimiliar = linkBiTree.createLinkBiTreeByDefinitionSimilar(); 
        BiTreeNode rootSimiliar = biTreeSimiliar.root;
        System.out.println("判断两棵不同的二叉树是否相等: " + linkBiTree.isEqual(root, rootSimiliar));
        System.out.println("判断两棵相同的二叉树是否相等: " + linkBiTree.isEqual(root, root));
        
        String preOrder = "ABDHKECFIGJ";
        String inOrder  = "HKDBEAIFCGJ";
        LinkBiTree biTreeByPreAndIn = linkBiTree.createBiTreeByPreAndInOrder(preOrder, inOrder, 0, 0, preOrder.length());
        System.out.print("由前序和中序遍历序列得到的一棵二叉树的层序非递归遍历算法得到的序列为: ");
        biTreeByPreAndIn.levelOrderTraverse();
        System.out.println();
        
        String NumberSign = "ABDH#K###E##CFI###G#J##";
        LinkBiTree biTreeHasNumberSign = linkBiTree.creataBiTreeByPreHasNullSign(NumberSign);
        System.out.print("由表明空子树的前序遍历序列得到的一棵二叉树的层序非递归遍历算法得到的序列为: ");
        biTreeHasNumberSign.levelOrderTraverse();
        System.out.println();
        
        String seqBiTree = "ABCDEFGHIJ";
        LinkBiTree linkBiTreeBySeqBiTree = linkBiTree.createBiTreeBySeqBiTree(seqBiTree, 0);
        System.out.print("由完全二叉树的顺序存储结构得到的一棵二叉树的层序非递归遍历算法得到的序列为: ");
        linkBiTreeBySeqBiTree.levelOrderTraverse();
        System.out.println();
        
        
    }
    
}
  • 输出:
前序递归遍历算法得到的序列为:  ABDHKECFIGJ
中序递归遍历算法得到的序列为:  HKDBEAIFCGJ
后序递归遍历算法得到的序列为:  KHDEBIFJGCA
前序非递归遍历算法得到的序列为: ABDHKECFIGJ
中序非递归遍历算法得到的序列为: HKDBEAIFCGJ
后序非递归遍历算法得到的序列为: KHDEBIFJGCA
层序非递归遍历算法得到的序列为: ABCDEFGHIJK
在二叉树中查找字符D返回的结点的数据域为:D
在二叉树中查找字符W返回的结点为:null
二叉树中结点个数的统计结果为: 11
二叉树的深度为: 5
判断两棵不同的二叉树是否相等: false
判断两棵相同的二叉树是否相等: true
由前序和中序遍历序列得到的一棵二叉树的层序非递归遍历算法得到的序列为: ABCDEFGHIJK
由表明空子树的前序遍历序列得到的一棵二叉树的层序非递归遍历算法得到的序列为: ABCDEFGHIJK
由表明空子树的前序遍历序列得到的一棵二叉树的层序非递归遍历算法得到的序列为: ABCDEFGHIJ

  另:所用到的链栈、链队列实现:

  • package bigjun.iplab.linkStack;
    
    public class Node {
        
        public Object data;   // 存放结点的数据元素的数据域(int类型不能设置null,而Object类型可以)
        public Node next;      // 存放后继元素的引用
        
        // 可实现初始化一个空的结点
        public Node() {
            this(null, null);
        }
        
        // 可实现构造一个数据域值为指定参数值,而指针域为空的结点
        public Node(Object data) {
            this(data, null);
        }
        
        // 可实现构造一个数据域和指针域值都为指定参数的结点
        public Node(Object data, Node next) {
            this.data = data;
            this.next = next;
        }
        
    }
    链栈结点类
  • package bigjun.iplab.linkStack;
    
    public class LinkStack implements IListStack {
        
        private Node top;
        
        public boolean isStackEmpty() {
            return top == null;
        }
    
        public void stackClear() {
            top = null;
        }
    
        public int stackLength() {
            Node pNode = top;     // 初始化,pNode指向栈顶元素
            int length = 0;       // length为计数器
            while (pNode != null) {
                pNode = pNode.next;
                ++length;
            }
            return length;
        }
    
        public Object getTopElem() throws Exception {
            if (!isStackEmpty()) {
                return top.data;
            } else {
                throw new Exception("栈为空,无法获取栈顶元素");
            }
        }
    
        public void stackPush(Object e) {
            Node p = new Node(e);
            p.next = top;
            top = p;
        }
    
        public Object stackPop() throws Exception {
            if (isStackEmpty()) 
                throw new Exception("栈为空,无法弹出栈顶元素");
            else {
                Node p = top;
                top = top.next;
                return p.data;
            }
        }
    
        public void stackTraverse() {    // 从栈顶元素到栈底元素
            Node p = top;
            System.out.print("此时,链栈中的元素为: ");
            while (p != null) {
                System.out.print(p.data.toString() + " ");
                p = p.next;
            }
            System.out.println();
        }
        
        public static void main(String[] args) throws Exception {
            LinkStack lStack = new LinkStack();
            for (int j = 1; j <= 10; j++) {
                lStack.stackPush(j);
            }
            lStack.stackTraverse();
            
            System.out.println("栈顶元素为: " + lStack.getTopElem());
            System.out.println("栈是否为空: " + lStack.isStackEmpty());
            
            lStack.stackPop();
            lStack.stackTraverse();
            System.out.println("栈顶元素为: " + lStack.getTopElem());
            
            lStack.stackClear();
            System.out.println("栈是否为空: " + lStack.isStackEmpty());
        }
    
    }
    链栈实现类
  • package bigjun.iplab.linkQueue;
    
    import bigjun.iplab.linkStack.Node;
    
    public class LinkQueue implements LinkQueueINF{
        
        private Node front;     // 队头指针指向头结点
        private Node rear;      // 队尾指针指向终端结点
        
        public LinkQueue() {
            front = rear = null;
        }
    
        public boolean isqueueEmpty() {
            return front == null;              // 判断链队列为空时,只需观察front结点是否为空即可
        }
    
        public void queueClear() {
            front = rear = null;
        }
    
        public int queueLength() {
            int length = 0;
            Node p = front;
            while (p != null) {
                p = p.next;
                ++ length;
            }
            return length;
        }
    
        public Object getHeadElem() throws Exception {
            if (front == null) 
                throw new Exception("链队列为空,无法获取队头元素");
            return front.data;
        }
    
        public void queueEnter(Object e){
            Node p = new Node(e);
            if (front != null) {
                rear.next = p;
                rear = p;
            } else {
                front = rear = p;
            }
        }
    
        public Object queuePoll() throws Exception {
            if (front != null) {        // 如果队列不为空
                Node p = front;            // p指向被删除的队头结点
                front = front.next;        // 队头结点出队列
                if (p == rear)             // 队列只有一个结点,front和rear都是这个结点
                    rear = null;        // 令队尾结点为空
                return p.data;            // 返回被删除的结点的数据域
            } else {
                throw new Exception("链队列为空,无法删除队头元素并返回");
            }
        }
    
        public void queueTraverse() {
            Node p = front;
            System.out.print("此时,链队列中的元素为: ");
            while (p != null) {
                System.out.print(p.data + " ");
                p = p.next;
            }
            System.out.println();
        }
        
        public static void main(String[] args) throws Exception {
            LinkQueue lQueue = new LinkQueue();
            lQueue.queueEnter(-5);
            lQueue.queueTraverse();
            System.out.println("此时,链队列的长度为: " + lQueue.queueLength());
            
            lQueue.queueEnter(5);
            lQueue.queueEnter(10);
            lQueue.queueTraverse();
            System.out.println("此时,链队列的长度为: " + lQueue.queueLength());
            System.out.println("此时,链队列的头结点元素为: " + lQueue.getHeadElem());
            
            lQueue.queuePoll();
            lQueue.queueTraverse();
            System.out.println("此时,链队列的长度为: " + lQueue.queueLength());
            System.out.println("此时,链队列的头结点元素为: " + lQueue.getHeadElem());
            
            lQueue.queueClear();
            System.out.println("此时,链队列是否为空: " + lQueue.isqueueEmpty());
            
        }
        
    
    }
    链队列实现类

     

  

posted @ 2018-06-23 18:01  BigJunOba  阅读(1881)  评论(0编辑  收藏  举报