一些算法的知识

今晚的主题

  • 二叉树的构建,遍历
  • ArrayList和LinkedList的区别
  • 使用LinkedList构建栈

首先我们来看一下怎么遍历这个二叉树,常规的有三种方式:
先序遍历:根左右
中序遍历:左根右
后序遍历:左右根
二叉树的遍历
那么java代码应该怎么实现呢?我在网上找了一个比较常规的写法

首先我们需要一个Node类,用来存储每个节点的值

package com.test.letcode;

/**
 * 二叉树的节点
 */
public class Node {
    Node leftNode;
    Node rightNode;
    int data;

    public Node(int insertData) {
        leftNode = null;
        rightNode = null;
        data = insertData;
    }

}

有了节点Node以后,我们就可以构建二叉树了,所以我们需要一个CreateTree类

package com.test.letcode;

import java.util.LinkedList;
import java.util.List;

/**
 * 创建树
 */
public class CreateTree {
    private List<Node> nodeList = new LinkedList<>();
    private int[] datas = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    public List<Node> createTree() {
        // 将数组中的值转换为一个个的Node存入nodeList
        for (int data : datas) {
            nodeList.add(new Node(data));
        }

        // 遍历nodeList,二叉树一共会有(总节点数/2)个父节点,这个地方由于最后一个节点
        // 需要特殊处理,所以减了一个1
        // 然后按照节点数的索引将值赋值给每个节点
        for (int index = 0; index < datas.length / 2 - 1; index++) {
            nodeList.get(index).leftNode = nodeList.get(index * 2 + 1);
            nodeList.get(index).rightNode = nodeList.get(index * 2 + 2);
        }

        int lastIndex = datas.length / 2 - 1;
        // 左孩子
        nodeList.get(lastIndex).leftNode = nodeList.get(lastIndex * 2 + 1);
        // 有可能最后一个节点没有右孩子,所以需要判断一下
        if (datas.length % 2 == 1) {
            nodeList.get(lastIndex).rightNode = nodeList.get(lastIndex * 2 + 2);
        }

        return nodeList;
    }
}

构建以后,我们就开始遍历,所以我们需要一个IteratorTree类

package com.test.letcode;

import java.util.List;

/**
 * 遍历树
 */
public class IteratorTree {
    // 先序遍历 根左右
    public void preorderTraversal(Node node) {
        if (node == null) {
            return;
        }
        System.out.print(node.data + " ");
        preorderTraversal(node.leftNode);
        preorderTraversal(node.rightNode);
    }

    // 中序遍历 左根右
    public void inOrderTraversal(Node node) {
        if (node == null) {
            return;
        }
        inOrderTraversal(node.leftNode);
        System.out.print(node.data + " ");
        inOrderTraversal(node.rightNode);
    }

    // 后序遍历 左右根
    public void postOrderTraversal(Node node) {
        if (node == null) {
            return;
        }
        postOrderTraversal(node.leftNode);
        postOrderTraversal(node.rightNode);
        System.out.print(node.data + " ");
    }

    public static void main(String[] args) {
        CreateTree createTree = new CreateTree();
        List<Node> nodeList = createTree.createTree();
        IteratorTree iteratorTree = new IteratorTree();
        System.out.println("先序遍历");
        iteratorTree.preorderTraversal(nodeList.get(0));
        System.out.println();
        System.out.println("中序遍历");
        iteratorTree.inOrderTraversal(nodeList.get(0));
        System.out.println();
        System.out.println("后序遍历");
        iteratorTree.postOrderTraversal(nodeList.get(0));
    }
}

最终的输出结果:
result
和我们期望的结果是一致的

下来是我们的第二个问题,ArrayList和LinkedList的区别

  1. ArrayList的实现是基于数组来实现的,LinkedList的基于双向链表来实现。这两个数据结构的逻辑关系是不一样,当然物理存储的方式也会是不一样。

  2. 对于随机访问,ArrayList优于LinkedList。

  3. 对于插入和删除操作,LinkedList优于ArrayList

  4. LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。

上面是我在网上搜到的结果,我自己也很认同,感觉这个东西只要记住了,面试问到了能够答出来就行

最后一个问题,使用LinkedList构建栈

首先我们来构建一个栈,栈的结构我们都知道,先进后出,后入先出;所以我们来构建一个Stack类

package com.test.letcode;

import java.util.LinkedList;

/**
 * 栈结构
 */
public class Stack {
    LinkedList<Integer> data = new LinkedList<>();

    // 入栈
    public void push(int val) {
        data.push(val);
    }

    // 出栈
    public void pop() {
        data.pop();
    }

    public void print() {
        data.forEach(System.out::println);
    }
}

然后我们来尝试入栈和出栈,但是其实说白了,LinkedList就像是一个栈结构一样,提供给了我们push和pop的方法

package com.test.letcode;

public class TestStack {
    public static void main(String[] args) {
        Stack stack = new Stack();
        stack.push(1);
        stack.push(2);
        stack.push(3);

        System.out.println("入栈以后的结果");
        stack.print();

        for (int index = 0; index < 3; index++) {
            System.out.println("出栈的结果");
            stack.print();
            stack.pop();
        }
    }
}

输出的结果如下:
stack
符合栈的规则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值