链表与二叉树

链表

链表是一组不必连续存储的、通过内存地址确定两两元素位置关系的内存结构。

数组和链表的区别:

数组:

是连续存储的线性结构,元素类型相同、大小相等。

  • 优点:

    查找速度快。

  • 缺点:

    数组长度固定,增删慢,需要开辟大块内存空间。

链表:

n个节点离散分配,一个结点包含两部分:储存元素的数据域,储存内存地址的指针域。每个节点最多有一个前驱结点和一个后驱结点,节点之间通过指针连接,用于存储前一个元素的内存地址和后一个元素的内存地址。

  • 优点:

    空间没有限制,增删速度快。

  • 缺点:

    查找速度慢。

链表的种类

链表分为三种:单向链表、双向链表、循环链表。其中循环列表又分为单向循环链表和双向循环链表。

不同链表的结构图解如下:


二叉树

由结点组成的树状数据结构,每个结点最多可有两个子树,一般储存有序的元素。

二叉树结构优点

查找快。

二叉树遍历方式

先序遍历:根 -> 左 -> 右

中序遍历:左 -> 根 -> 右

后序遍历:左 -> 右 -> 根

手动构建二叉树

我们使用代码构建一个形如下图的二叉树结构:

首先定义结点类,代码如下:

public class TreeNode<T> {
    private T data;
    private TreeNode left;
    private TreeNode right;

    public TreeNode(){}
    public TreeNode(T data){
        this.data = data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}

在程序入口中,设置结点的子节点,代码如下:

    public static void main(String[] args) {
        TreeNode<Integer> root = new TreeNode<>(1);
        TreeNode<Integer> node2 = new TreeNode<>(2);
        TreeNode<Integer> node3 = new TreeNode<>(3);
        TreeNode<Integer> node4 = new TreeNode<>(4);
        TreeNode<Integer> node5 = new TreeNode<>(5);
        TreeNode<Integer> node6 = new TreeNode<>(6);
        TreeNode<Integer> node7 = new TreeNode<>(7);

        //根结点的两个子节点
        root.setLeft(node2);
        root.setRight(node3);

        node2.setLeft(node4);
        node2.setRight(node5);

        node3.setLeft(node6);
        node3.setRight(node7);
    }

构建出的二叉树,效果图如下:

按层遍历二叉树(按深度遍历二叉树)

代码如下:

    public static void printByLayer(TreeNode node) {
        if (node == null)
            return;

        //队列特点:先进先出
        Queue<TreeNode> queue = new LinkedList<>();

        queue.add(node);

        while (queue.size() != 0) {
            TreeNode pollNode = queue.poll();
            System.out.println(pollNode.getData());

            TreeNode left = pollNode.getLeft();

            TreeNode right = pollNode.getRight();
            if (left != null) {
                queue.add(left);
            }

            if (right != null) {
                queue.add(right);
            }
        }

    }

程序入口中将根结点传入,运行结果如下:

1
2
3
4
5
6
7

前序遍历二叉树

代码如下:

    /**
     * 前序遍历
     */
    public static void pre_print(TreeNode node) {
        if (node == null)
            return;

        TreeNode left = node.getLeft();
        TreeNode right = node.getRight();

        System.out.println(node.getData());

        if (left != null){
            pre_print(left);
        }

        if (right != null)
            pre_print(right);
    }

程序入口中将根结点传入,运行结果如下:

1
2
4
5
3
6
7

中序遍历二叉树

代码如下:

    /**
     * 中序遍历
     */
    public static void mid_print(TreeNode node) {
        if (node != null) {
            TreeNode left = node.getLeft();
            TreeNode right = node.getRight();

            if (left != null) {
                mid_print(left);
            }

            System.out.println(node.getData());

            if (right != null) {
                mid_print(right);
            }
        }
    }

程序入口中将根结点传入,运行结果如下:

4
2
5
1
6
3
7

后序遍历二叉树

代码如下:

    public static void last_print(TreeNode node){
        TreeNode left = node.getLeft();
        TreeNode right = node.getRight();

        if (left.getLeft() != null)
            last_print(left);
        else
            System.out.println(left.getData());

        if (right.getRight() != null)
            last_print(right);
        else
            System.out.println(right.getData());

        System.out.println(node.getData());
    }

程序入口中将根结点传入,运行结果如下:

4
5
2
6
7
3
1
posted on 2021-10-14 22:07  技术小伙伴  阅读(311)  评论(0)    收藏  举报