树型结构的定义与基本操作

104 阅读5分钟

Java版

import java.util.*;

//二叉树结点
class Node {
    Integer value;
    Node left,right;


    public Node(Integer value) {
        this.value = value;
    }
}


//二叉树
class BinaryTree {

    Node root;

    public Node getRoot() {
        return root;
    }



    //创建二叉树
    public Node Creat(ArrayList<Integer> inputList) {
        if (inputList == null || inputList.isEmpty()) {
            return null;
        }
        Node node = null;
        Integer value = inputList.remove(0);
        if (value != null) {
            node = new Node(value);
            node.left = Creat(inputList);
            node.right = Creat(inputList);
        }
        return node;
    }

    //先序遍历
    public void preOrderTraversal(Node root) {
        if (root == null) {
            return;
        }
        System.out.print(root.value);
        preOrderTraversal(root.left);
        preOrderTraversal(root.right);
    }


    //中序遍历(非递归)
    void InOrder2(Node root)
    {
        Stack <Node> s = new Stack<>();
        Node p = root;

        while(p!=null || !s.empty())
        {
            if(p!=null)     //遍历左子树,依次进栈
            {
                s.push(p);
                p=p.left;
            }
            else      //退栈,访问根节点。遍历右子树
            {
                p = s.pop();
                System.out.println(p.value);
                p=p.right;
            }
        }
    }



    // 深度
    public int Depth(Node root){
        if(root==null){
            return 0;
        }
        int m = Depth(root.left);
        int n = Depth(root.right);
        return m>n? m+1:n+1;
    }


    public  int NodeCount(Node root){
        //统计二叉树中结点的个数
        if(root==null) return 0;
        else return NodeCount(root.left)+NodeCount(root.right)+1;
    }


    int LeafCount(Node root)
    {
        //统计二叉树中叶子结点的个数
        if(root==null) return 0;
        if(root.left==null && root.right==null) return 1;
        else return LeafCount(root.left)+LeafCount(root.right);

    }

    int Node_1_Count(Node root)
    {
        //统计二叉树的度为1的结点个数
        if(root==null) return 0;
        if((root.left==null)&&(root.right!=null)||(root.left!=null)&&(root.right==null))
            return 1;
        else
            return LeafCount(root.left)+LeafCount(root.right);
    }
    void PrintAllPath(Node root, int path[], int pathlen)
    {
        //二叉树中从每个叶子结点到根结点的路径
        int i;
        if(root != null)
        {
            path[pathlen] = root.value; //将当前结点放入路径中
            if(root.left==null && root.right==null)  //叶子结点
            {
                for(i = pathlen; i >= 0; i--){
                    System.out.println(path[i]);
                }
                System.out.println();

            }
            else
            {
                PrintAllPath(root.left, path, pathlen + 1);
                PrintAllPath(root.right, path, pathlen + 1);
            }
        }
    }


    public  void levelOrderTraversal (Node node) {
        Queue<Node> queue = new LinkedList<Node>();
        queue.offer(node);
        while (!queue.isEmpty()) {
            node = queue.poll();
            System.out.print(node.value + " ");
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
    }


    // BFS层次打印层次遍历的结果
    // https://blog.nowcoder.net/n/0f27800916264398bc7e4c5c16191009
    // https://blog.nowcoder.net/n/60c2b2e2bd7440b5ab8ce47784d25139
    ArrayList<ArrayList<Integer>> Print(Node pRoot) {
        ArrayList<ArrayList<Integer>> thelist = new ArrayList<ArrayList<Integer>>();
        if(pRoot==null)return thelist; //这里要求返回thelist而不是null
        Queue<Node> queue = new LinkedList<Node>();
        queue.offer(pRoot);
        while(!queue.isEmpty()){
            ArrayList<Integer> list = new ArrayList<Integer>();
            int size = queue.size();
            for(int i=0;i<size;i++){
                pRoot = queue.poll();
                list.add(pRoot.value);
                if (pRoot.left != null) {
                    queue.offer(pRoot.left);
                }
                if (pRoot.right != null) {
                    queue.offer(pRoot.right);
                }
            }
            thelist.add(list);
        }
        return thelist;
    }




    // 递归创建二叉查找树
    public  Node insert_1(Node root, int val){
        if(root==null)
            return new Node(val);
        if(root.value<val)
            root.right = insert_1(root.right,val);
        else if(root.value>val)
            root.left = insert_1(root.left,val);
        else
            root.value = val;
        return root;
    }




     // 非递归创建二叉查找树
    public static Node insert_2(Node root, int val) {
        if (root == null) {
            return new Node(val);
        }
        Node temp = root;
        Node curr;
        while (root != null) {
            curr = root;
            if (root.value < val) {
                root = root.right;
                if(root==null){
                    curr.right = new Node(val);
                    return temp;
                }

            } else if (root.value > val) {
                root = root.left;
                if(root==null){
                    curr.left = new Node(val);
                    return temp;
                }
            }
            else {
                System.out.println("已经有这个值了");
                return temp;
            }
        }
        return temp;
    }






}


public class A {

    public static void main(String[] args) {
        // 用来输入的数据
        Integer[] input = new Integer[]{1, 2, 3, null, null, 4, null, null, 5, null, 6};
        ArrayList inputList = new ArrayList(Arrays.asList(input));

        // 初始化树,返回树结点
        BinaryTree tree = new BinaryTree();
        Node root = tree.getRoot();


//        // 前序递归建立普通树
//        root = tree.Creat(inputList);




       // 创建二叉查找树
        root=  tree.insert_1(root, 3);  // 按理来说每个插入语句都要用root来接收。这里为了方便,只在第一个语句接收,防止刚开始时是空树的情况
        tree.insert_1(root, 8);
        tree.insert_1(root, 2);
        tree.insert_1(root, 1);
        tree.insert_1(root, 9);
        tree.insert_1(root, 0);
        tree.insert_1(root, 6);
        tree.insert_1(root, 7);
        tree.insert_1(root, 4);




        System.out.print("先序遍历:");
        tree.preOrderTraversal(root);
        System.out.println();

        System.out.print("层次遍历:");
        tree.levelOrderTraversal(root);
        System.out.println();

        System.out.print("层次打印:");
        System.out.println(tree.Print(root));

        System.out.print("深度:");
        System.out.println(tree.Depth(root));

        System.out.print("结点个数:");
        System.out.println(tree.NodeCount(root));



        System.out.println("叶结点的个数:");
        System.out.println(tree.LeafCount(root));


        System.out.println("度为1的结点个数:");
        System.out.println(tree.Node_1_Count(root));




        System.out.println("二叉树中从每个叶子结点到根结点的所有路径:");
        int[] path = new int[256];
        int pathlen=0;
        tree.PrintAllPath(root,path,pathlen);




    }
}



C++版(链表实现)

#include <iostream>
#include <stack>
#include <queue>
using namespace std;

//定义二叉树结构
typedef struct Node
{
    char data;
    struct Node *lchild,*rchild;
}*BiTree,BiTNode;


//先序创建二叉树
void CreateBiTree(BiTree &T)
{
    char ch;
    cin>>ch;
    if(ch=='#') T=NULL;
    else
    {
        T=new BiTNode;
        T->data=ch;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
}


//先序遍历
void PreOrder(BiTree T)
{
    if(T)
    {
        cout<<T->data;
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    }
}


//中序遍历
void InOrder1(BiTree T)
{
    if(T)
    {
        InOrder1(T->lchild);
        cout<<T->data;
        InOrder1(T->rchild);
    }
}


//后序遍历
void PostOrder(BiTree T)
{
    if(T)
    {
        PostOrder(T->lchild);
        PostOrder(T->rchild);
        cout<<T->data;
    }
}


//中序遍历(非递归)
void InOrder2(BiTree T)
{
    stack <BiTree>s;
    BiTree p = T;

    while(p || !s.empty())
    {
        if(p)     //遍历左子树,依次进栈
        {
            s.push(p);
            p=p->lchild;
        }
        else      //退栈,访问根节点。遍历右子树
        {
            p=s.top();
            cout<<p->data;
            s.pop();
            p=p->rchild;
        }
    }
}


//层次遍历
void LevelOrder(BiTree T)
{
    queue<BiTree> q;
    BiTree p=T;

    q.push(p);
    while(!q.empty())
    {
        p=q.front();
        cout<<q.front()->data;
        q.pop();
        if(p->lchild)
            q.push(p->lchild);
        if(p->rchild)
            q.push(p->rchild);
    }
}


//双序遍历
void DblOrder(BiTree T)
{
    if(T)
    {
        cout<<T->data;
        DblOrder(T->lchild);
        cout<<T->data;//访问两遍
        DblOrder(T->rchild);
    }
}


//二叉树的复制
void Copy(BiTree T , BiTree &NewT)
{
    if(T==NULL)
    {
        NewT=NULL;
        return;
    }
    else
    {
        NewT=new BiTNode;
        NewT->data=T->data;
        Copy(T->lchild,NewT->lchild);
        Copy(T->rchild,NewT->rchild);
    }
}

//树的深度
int Depth(BiTree T)
{
    if(T==NULL)
        return 0;
    else
    {
        int m=Depth(T->lchild);
        int n=Depth(T->rchild);
        if(m>n)
            return (m+1);
        else
            return (n+1);
    }
}

//统计二叉树中结点的个数
int Node_Count(BiTree T)
{
    if(T==NULL)
        return 0;
    else
        return Node_Count(T->lchild) + Node_Count(T->rchild) + 1 ;
}

//统计二叉树中叶子结点的个数
int Leaf_Count(BiTree T)
{
    if(!T)
        return 0;
    if(!T->lchild && !T->rchild) //如果二叉树左子树和右子树皆为空,说明该二叉树根节点为叶子节点,加1.
        return 1;
    else
        return Leaf_Count(T->lchild) + Leaf_Count(T->rchild);
}

//统计二叉树的度为1的结点个数
int Node_1_Count(BiTree T)
{
    if(!T)
        return 0;
    if((!T->lchild) && (T->rchild) || (T->lchild) && (!T->rchild))
        return 1;
    else
        return Leaf_Count(T->lchild) + Leaf_Count(T->rchild);
}

//二叉树中从每个叶子结点到根结点的路径
void Print_All_Path(BiTree T, char path[], int pathlen)
{
    int i;
    if(T != NULL)
    {
        path[pathlen] = T->data; //将当前结点放入路径中
        if(T->lchild == NULL && T->rchild == NULL)  //叶子结点
        {
            for(i = pathlen; i >= 0; i--)
                cout << path[i] << " " ;
            cout << endl;
        }
        else
        {
            Print_All_Path(T->lchild, path, pathlen + 1);
            Print_All_Path(T->rchild, path, pathlen + 1);
        }
    }
}

//构造函数,使用递归算法进行左右结点转换
void ExChangeTree(BiTree &T)
{
    BiTree temp;
    if(T!=NULL) //判断T是否为空,非空进行转换,否则不转换
    {
        temp=T->lchild;
        T->lchild=T->rchild;//直接交换节点地址
        T->rchild=temp;
        ExChangeTree(T->lchild);
        ExChangeTree(T->rchild);
    }
}



int main()
{
    BiTree T;
    //测试例子AB#CD##E##F#GH###
    cout<<"先序遍历输入(以#结束):";
    CreateBiTree(T);
    cout<<"中序遍历(非递归):";
    InOrder2(T);
    cout<<endl<<"中序遍历输出:";
    InOrder1(T);
    cout<<endl<<"先序遍历输出:";
    PreOrder(T);
    cout<<endl<<"后序遍历输出:";
    PostOrder(T);
    cout<<endl<<"层次遍历输出:";
    LevelOrder(T);
    cout<<endl<<"树的深度:"<<Depth(T);
    cout<<endl<<"结点的个数:"<<Node_Count(T);
    cout<<endl<<"叶结点的个数:"<<Leaf_Count(T);
    cout<<endl<<"度为1的结点个数:"<<Node_1_Count(T);
    cout<<endl<<"二叉树中从每个叶子结点到根结点的所有路径:"<<endl;

    char path[256];
    int pathlen=0;
    Print_All_Path(T,path,pathlen);//
    //交换二叉树每个结点的左孩子和右孩子
    BiTree tem=T;//直接复制一颗树,在不改变原树的前提下,对临时树进行交换。
    ExChangeTree(tem);
    cout<<"先序遍历输出交换后的结果:";
    PreOrder(tem);
    cout<<endl<<"双序遍历输出:";
    DblOrder(T);
    return 0;
}