Data structure -- 01

Posted by bizerk on Mon, 31 Jan 2022 03:10:24 +0100

Data structure and algorithm relationship

  • Data structure data structure is a subject that studies the way of organizing data. With programming language, there will be data structure and write more beautiful and efficient code
  • To learn data structure, we should consider more problems in life and solve them with programs
  • Program = data structure + algorithm
  • Data structure is the basis of algorithm

Linear structure and nonlinear structure

linear structure

Array queue linked list stack

As the most commonly used data structure, linear structure is characterized by one-to-one linear relationship between data elements

Linear structure has two different storage structures, sequential structure and chain structure

Sequential structure linear table is a sequential table, which stores continuous elements

Linked storage linear list is called linked list. The storage elements in the linked list are not necessarily continuous, and the address information of elements and adjacent elements are stored in the element node

Nonlinear structure

Two dimensional array, multi-dimensional array, generalized table, tree structure, graph structure

Sparse array

Basic introduction

Most elements of an array are 0, or an array with the same value. Sparse array is used to save the array

Sparse array processing:

  1. Record array row and column, value
  2. Record the element rows, columns and values with different values in a small-scale array to reduce the size of the program

Idea of converting two-dimensional array to sparse array:

  1. Traverse the original two-dimensional array and record the number of valid data
  2. Create sparsearr int [sum] [3] from sum
  3. Store the valid data of two-dimensional array into sparse array

Idea of converting sparse array to two-dimensional array:

  1. Read the first row of the sparse array and create the original two-dimensional array according to the data. chessArr2 = int [11] [11]
  2. Read a few lines of data after the sparse array and assign them to the original two-dimensional array
package com.fu.datastruct;

public class SparseArr {
    public static void main(String[] args) {
        int sum = 0;
        //Output 2D array
        int[][] chessArr1 = new int[11][11];
        chessArr1[3][3] = 4;
        chessArr1[4][4] = 5;
        for (int[] c1 : chessArr1) {
            for (int c2 : c1) {
                System.out.printf("%d\t",c2);
                if (c2 != 0){
                    sum+=1;
                }
            }
            System.out.println();
        }
        System.out.println("Valid values:"+sum);
        //2D array to sparse array
        System.out.println("Output sparse array~~");
        int[][] sparseArr = new int[sum + 1][3];
        sparseArr[0][0] = 11;
        sparseArr[0][1] = 11;
        sparseArr[1][1] = sum;
        int count = 0;
        for (int i = 0; i < chessArr1.length; i++) {
            for (int j = 0; j < chessArr1[i].length; j++) {
                if (chessArr1[i][j] != 0){
                    count++;
                    sparseArr[count][0] = i;
                    sparseArr[count][1] = j;
                    sparseArr[count][2] = chessArr1[i][j];
                }
            }
        }
        for (int[] s1 : sparseArr) {
            for (int s2 : s1) {
                System.out.printf("%d\t",s2);
            }
            System.out.println();
        }
        System.out.println("Output 2D array~~");
        int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
        for (int i = 1; i < sparseArr.length; i++) {
            chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }
        for (int[] c1 : chessArr2) {
            for (int c2 : c1) {
                System.out.printf("%d\t",c2);
            }
            System.out.println();
        }
    }
}

queue

Queue introduction

  1. Queue is a sequential list, which can be realized by array or linked list
  2. First in first out

Array simulation queue

  1. The queue itself is an ordered queue. If the array structure is used to store queue data, the queue array declares that maxSIze is the maximum capacity of the queue
  2. Queue input and output: the input is processed from the front to the back. front rear records the subscripts at the front and back ends of the queue. Front changes with the data output, and rear changes with the input
package com.fu.datastruct.queue;


import java.util.Scanner;

public class ArrayQueueDemo {
    public static void main(String[] args) {
        ArrayQueue queue = new ArrayQueue(3);
        char key = ' ';
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        while(loop){
            System.out.println("s(show) Show queue");
            System.out.println("e(exit) Exit queue");
            System.out.println("a(add) Add data to queue");
            System.out.println("g(get) Fetch data from queue");
            System.out.println("h(head) View queue header data");
            key = scanner.next().charAt(0);
            switch (key){
                case 'a':
                    int i = scanner.nextInt();
                    queue.addQueue(i);
                    break;
                case 'g':
                    try {
                        int r = queue.getQueue();
                        System.out.println("The number taken out is:" + r);
                    } catch (Exception e) {
                        e.getMessage();
                    }
                    break;
                case 's':
                    queue.showQueue();
                    break;
                case 'h':
                    try {
                        int h = queue.headQueue();
                        System.out.println("The number taken out is:" + h);
                    } catch (Exception e) {
                        e.getMessage();
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;


            }
    }
        System.out.println("Exit program~~");
}}
class ArrayQueue{
    private int maxSize;
    private int front;
    private int rear;
    private int []arr;

    public ArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        front = -1;
        rear = -1;
        arr = new int[maxSize];
    }
    public boolean isFull(){
        return rear == maxSize -1;
    }
    public boolean isEmpty(){
        return rear == front;
    }
    public void addQueue(int n){
        if (isFull()){
            System.out.println("The queue is full and cannot be joined");
            return;
        }
        rear++;
        arr[rear] = n;
    }
    public int getQueue(){
        if (isEmpty()){
            throw new RuntimeException("The queue is empty, unable to fetch header data");
        }
        front++;
        return arr[front];
    }
    public void showQueue(){
        if (isEmpty()){
            System.out.println(("The queue is empty, unable to fetch header data"));
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("arr[%d]=%d\n",i,arr[i]);
        }
    }
    public int headQueue(){
        if (isEmpty()){
            throw new RuntimeException("The queue is empty, unable to fetch header data");
        }
        return arr[front + 1];
    }
}

Problem analysis and Optimization:

  1. At present, the array cannot be used once, which does not achieve the effect of reuse
  2. Use this array algorithm to improve a ring array%

Array simulation ring queue

  1. Adjustment of the meaning of the front variable: front points to the first element of the queue, arr[front] is the first element of the queue, and the initial value of front is 0
  2. Adjustment of the meaning of the rear variable: rear points to the position after the last element in the queue, because you want to make a space available as a convention. The initial value of rear is 0
  3. If the queue is full, the condition is (rear + 1)% maxsize = front [Full]
  4. For the condition that the queue is empty, rear == front is empty
  5. According to our analysis, the number of valid data in the queue [rear + maxsize - front]% maxsize
package com.fu.datastruct.queue;

import java.util.Scanner;

public class CircleQueueDemo {
    public static void main(String[] args) {
        CircleQueue queue = new CircleQueue(4);
        char key = ' ';
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        while(loop){
            System.out.println("s(show) Show queue");
            System.out.println("e(exit) Exit queue");
            System.out.println("a(add) Add data to queue");
            System.out.println("g(get) Fetch data from queue");
            System.out.println("h(head) View queue header data");
            key = scanner.next().charAt(0);
            switch (key){
                case 'a':
                    int i = scanner.nextInt();
                    queue.addQueue(i);
                    break;
                case 'g':
                    try {
                        int r = queue.getQueue();
                        System.out.println("The number taken out is:" + r);
                    } catch (Exception e) {
                        e.getMessage();
                    }
                    break;
                case 's':
                    queue.showQueue();
                    break;
                case 'h':
                    try {
                        int h = queue.headQueue();
                        System.out.println("The number taken out is:" + h);
                    } catch (Exception e) {
                        e.getMessage();
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;


            }
        }
        System.out.println("Exit program~~");
    }}
class CircleQueue{
    private int maxSize;
    private int front;
    private int rear;
    private int []arr;

    public CircleQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
    }
    public boolean isFull(){
        return (rear + 1) % maxSize == front;
    }
    public boolean isEmpty(){
        return rear == front;
    }

    public void addQueue(int n){
        if (isFull()){
            System.out.println("The queue is full and cannot be joined");
            return;
        }
        arr[rear] = n;
        rear = (rear + 1)%maxSize;
    }
    public int getQueue(){
        if (isEmpty()){
            throw new RuntimeException("The queue is empty, unable to fetch header data");
        }
        int value = arr[front];
        front = (front + 1 )%maxSize;
        return value;
    }
    public void showQueue(){
        if (isEmpty()){
            System.out.println(("The queue is empty, unable to fetch header data"));
        }
        for (int i = front; i < front + size(); i++) {
            System.out.printf("arr[%d]=%d\n",i % maxSize,arr[i%maxSize]);
        }
    }
    public int size(){
        return (rear - front + maxSize) % maxSize;
    }
    public int headQueue(){
        if (isEmpty()){
            throw new RuntimeException("The queue is empty, unable to fetch header data");
        }
        return arr[front];
    }


}

Single linked list

Introduction to linked list

  1. Linked lists are stored as nodes
  2. Each node contains a data field and the next field points to the next node
  3. Each node is not necessarily continuous storage
  4. The linked list is divided into the linked list with the leading node and the linked list without the head node, which is determined according to the demand

Implementation of addition, deletion and interpolation code

package com.fu.datastruct.queue;

public class SingleLinkedListDemo {
    public static void main(String[] args) {
        HeroNode h1 = new HeroNode(1, "Song Jiang", "Timely rain");
        HeroNode h2 = new HeroNode(2, "Lu Junyi", "Jade Unicorn");
        HeroNode h3 = new HeroNode(3, "Wu Yong", "Zhiduoxing");
        HeroNode h4 = new HeroNode(4, "Lin Chong", "Leopard head");
        SingleLinkedList s = new SingleLinkedList();
        s.addByOrder(h1);
        s.addByOrder(h4);
        s.addByOrder(h3);
        s.addByOrder(h2);

        s.list();
        System.out.println();
        s.del(1);
        s.update(new HeroNode(2,"Chao gai","Tota Kings "));
        s.list();
    }

}
class SingleLinkedList{
    private HeroNode head = new HeroNode(0,"","");
    public void add(HeroNode heroNode){//Add a heroNode
        HeroNode temp = head;
        while(true){
            if (temp.next == null)break;
            temp = temp.next;
        }
        temp.next = heroNode;
    }
    public void list(){
        if (head == null) {
            System.out.println("The linked list is empty");
            return;
        }
        HeroNode temp = head.next;
        while (true){
            if (temp == null){
                return;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }
    public void addByOrder(HeroNode heroNode){
        HeroNode temp = head;
        boolean flag = false;
        while(true){
            if (temp.next == null)break;
            else if (temp.next.no > heroNode.no)break;
            else if (temp.next.no == heroNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            System.out.println("Prepared hero number" + heroNode.no + "It already exists. You don't need to insert it");
        }else {
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }
    public void update(HeroNode newHero){
        if (head.next == null) {
            System.out.println("The linked list is empty");
            return;
        }
        HeroNode temp = head.next;
        boolean flag = false;
        while(true){
            if (temp == null){
                break;
            }
            else if (temp.no == newHero.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag){
            temp.name = newHero.name;
            temp.nickname = newHero.nickname;
        }
        else System.out.println("Can't find" + newHero.no + "No. hero, cannot be modified");
    }

    public void del(int no){
        HeroNode temp = head;
        boolean flag = false;
        while (true){
            if (temp.next == null) {
                break;
            }
            else if (temp.next.no == no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            temp.next = temp.next.next;
        }else System.out.println("No corresponding subscript hero, unable to delete");



    }


}
class HeroNode{
    public int no;
    public String name;
    public String nickname;
    public  HeroNode next;

    public HeroNode(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}


Bidirectional linked list

Disadvantages of single linked list

  1. One way linked list, there is only one search direction, and two-way linked list can search forward and backward
  2. A one-way linked list cannot be deleted by itself. It needs auxiliary nodes. A two-way linked list can be deleted by itself. When a single linked list is deleted, the node will always find temp. When temp is deleted, the previous node of the node to be deleted
package com.fu.datastruct.queue;

public class DoubleLinkedListDemo {
    public static void main(String[] args) {
        HeroNode2 h1 = new HeroNode2(1, "Song Jiang", "Timely rain");
        HeroNode2 h2 = new HeroNode2(2, "Wu Yong", "Zhiduoxing");
        HeroNode2 h3 = new HeroNode2(3, "Gongsun Sheng", "Ru Yunlong");
        DoubleLinkedList d = new DoubleLinkedList();
        d.add(h1);
        d.add(h2);
        d.add(h3);
        d.list();
        d.add(new HeroNode2(4 , "Dai Zong","Shenxing Taibao"));
        d.list();
    }
}
class DoubleLinkedList{
    private HeroNode2 head = new HeroNode2(0,"","");
    public void add(HeroNode2 heroNode){//Add a heroNode
        HeroNode2 temp = head;
        while(true){
            if (temp.next == null)break;
            temp = temp.next;
        }
        temp.next = heroNode;
        heroNode.pre = temp;
    }
    public void list(){
        if (head == null) {
            System.out.println("The linked list is empty");
            return;
        }
        HeroNode2 temp = head.next;
        while (true){
            if (temp == null){
                return;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }
    public void update(HeroNode2 newHero){
        if (head.next == null) {
            System.out.println("The linked list is empty");
            return;
        }
        HeroNode2 temp = head.next;
        boolean flag = false;
        while(true){
            if (temp == null){
                break;
            }
            else if (temp.no == newHero.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag){
            temp.name = newHero.name;
            temp.nickname = newHero.nickname;
        }
        else System.out.println("Can't find" + newHero.no + "No. hero, cannot be modified");
    }
    public void del(int no){
        HeroNode2 temp = head.next;
        if (head.next == null){
            System.out.println("The linked list is empty~");
        }
        boolean flag = false;
        while (true){
            if (temp == null) {
                break;
            }
            else if (temp.no == no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            temp.pre.next = temp.next;
            if (temp.next != null) temp.next.pre = temp.pre;

        }else System.out.println("No corresponding subscript hero, unable to delete");
    }
}
class HeroNode2{
    public int no;
    public String name;
    public String nickname;
    public HeroNode2 next;
    public HeroNode2 pre;

    public HeroNode2(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}

Joseph problem (circular linked list)

Use the circular linked list without the leading node to deal with it. First form a single circular linked list with n nodes. Count from node k from 1 until the corresponding node m is deleted. Count from the next node of the deleted node from 1 until the last node is deleted from the linked list

package com.fu.datastruct.queue;

public class Joseph {
    public static void main(String[] args) {
        CircleSingleLinkedList c = new CircleSingleLinkedList();
        c.addBoy(5);
        c.showBoy();
        c.countBoy(1,2,5);
    }

}
class CircleSingleLinkedList{
    private Boy first = null;
    public void addBoy(int nums){
        if (nums < 2) {
            System.out.println("nums The value of is incorrect");
            return;
        }
        Boy curBoy = null;//Auxiliary variable
        for (int i = 1; i <= nums ; i++) {
            //Create child variables by number
            Boy boy = new Boy(i);
            if (i == 1){
                first = boy;
                first.setNext(first);//Constituent ring
                curBoy = first;
            }else {
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }


        }

    }
    public void showBoy(){
        if (first == null){
            System.out.println("This is an empty linked list and cannot be traversed");
            return;
        }
        Boy curBoy = first;
        while (true){
            System.out.println("Child number:" + curBoy.getNo());
            if (curBoy.getNext() == first){
                break;
            }
            curBoy = curBoy.getNext();
        }
    }

    /**
     *
     * @param startNo  It means counting from the first child
     * @param countNum  It means counting
     * @param nums       Indicates that the first few children are in the circle
     */
    public void countBoy(int startNo,int countNum,int nums){
        if (first == null|| startNo < 1 || startNo > nums){
            System.out.println("Parameter input error, please re output");
            return;
        }
        Boy helper = first;
        while (true){
            if (helper.getNext() == first){//last
                break;
            }
            helper = helper.getNext();
        }
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        while(true){
            if (helper == first){//There is only one person in the circle
                break;
            }
            else {
                for (int i = 0; i < countNum - 1; i++) {
                    first = first.getNext();
                    helper = helper.getNext();
                }
                System.out.println("child" + first.getNo() + "Out of circle");
                first = first.getNext();
                helper.setNext(first);
            }

        }
        System.out.println("Finally, leave the child number in the circle" + first.getNo());




    }



}
class Boy{
    private int no;
    private Boy next;

    public Boy(int no) {
        this.no = no;
    }

    public Boy(int no, Boy next) {
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
}

Stack

  1. 1. Stack English stack
    2. Stack is**First in then out**Ordered list
    3. Stack is a special linear table that restricts the insertion and deletion of elements in a linear table to only be carried out at one end of the linear table. The end that allows insertion and deletion is the changing end, which is called**Stack top**,The other end is the fixed end, which is called**Stack bottom**
    4. According to the definition of stack, the first element put into the stack is at the bottom of the stack, the last element put into the stack is at the top of the stack, and the opposite is true for deleting elements. The last element put into the stack is deleted first, the first element put into the stack is deleted last
    

Application scenario

  1. Subroutine call: before jumping to the subroutine, first store the address of the next instruction in the stack until the subroutine is executed, and then take out the address to return to the original program
  2. Handling recursive calls: similar to subroutine calls, in addition to storing the next instruction address, it also stores parameters, area variables and other data into the stack
  3. Expression conversion and evaluation
  4. Binary tree traversal
  5. Graphic depth first search method
package com.fu.datastruct.stack;

import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import java.util.Scanner;
import java.util.Stack;

public class ArrayStackDemo {
    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack(4);
        boolean loop = true;
        String key = "";
        Scanner scanner = new Scanner(System.in);
        while(loop){
            System.out.println("push Stack operation");
            System.out.println("pop Stack out operation");
            System.out.println("list Print operation");
            System.out.println("exit Leave operation");
            System.out.println("Please enter your action:");
            key = scanner.next();
            switch (key){
                case "push":
                    System.out.println("Please enter the stack value:");
                    int value = scanner.nextInt();
                    stack.push(value);
                    break;
                case "pop":
                    stack.pop();
                    break;
                case "list":
                    stack.list();
                    break;
                case "exit":
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }

        }
        System.out.println("Exit program~~");
    }
}

class ArrayStack{
    private int[] stack;
    private int maxSize;
    private int top = -1;

    //constructor 
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[this.maxSize];
    }

    //Stack full
    public boolean isFull(){
        return top == maxSize - 1;
    }
    //Stack empty
    public boolean isEmpty(){
        return top == -1;
    }
    //Push 
    public void push(int value){
        if (isFull()){
            System.out.println("Stack full");
            return;
        }
        top++;
        stack[top] = value;
    }
    //Out of stack
    public int pop() {
        if (isEmpty()){
            throw new RuntimeException("Stack empty");
        }
        int value = stack[top];
        top--;
        return value;
    }
    //ergodic
    public void list(){
        if (isEmpty()){
            throw new RuntimeException("Stack empty");
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("stack[%d] = %d\n",i,stack[i]);
        }
    }

}

Prefix expression (Polish expression)

  1. Prefix expression is also known as polish. The operator of prefix expression precedes the operand
  2. (3 + 4) * 5-6 prefix expression - * + 3 4 5 6

Infix expression

Infix expression evaluation is a normal practice, which is not friendly to computer. Infix is often converted into suffix in calculation

Postfix Expression

  1. Suffix expressions are called inverse Polish expressions. Similar to prefix expressions, operators follow operands
  2. (3 + 4) * 5-6 suffix expression 3 4 + 5 * 6-
Normal expressionReverse Polish notation
a + ba b +
a + ( b - c)a b c - +
a + (b - c) * da b c - d * +
a + d * (b - c)a d b c - * +
a = 1 + 3a 1 3 + =

Scan the expression from left to right. When encountering a number, the number will be pushed into the stack. When encountering an operator, the two numbers at the top of the stack will pop up. Use the operator to calculate them accordingly and put the result into the stack: repeat the above process until the rightmost end of the expression, and finally get the result of the expression

Don't forget * / takes precedence over +-

Inverse Polish calculator

  1. Enter an inverse Polish expression (suffix expression), use stack, and calculate the result
  2. Supports parentheses and multi digit integers, which is a simplified calculator and only supports integer calculation
package com.fu.datastruct.stack;


import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class PolandNotation {
    public static void main(String[] args) {
        String str = "3 4 + 5 * 6 -";
        System.out.println(calculate(getListString(str)));

    }
    //Put data operators into ArrayList
    public static List<String> getListString(String str){
        String[] split = str.split(" ");
        List<String> list = new ArrayList<>();
        for (String s : split) {
            list.add(s);
        }
        return list;
    }
    //Complete the calculation of the inverse Polish expression
    public static int calculate(List<String> ls) {
        //To create a stack, you only need one stack
        Stack<String> stack = new Stack<>();
        for (String l : ls) {
            if (l.matches("\\d+")){
                stack.push(l);
            }
            else {
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if (l.equals("+")){
                    res = num1 + num2;
                }
                else if (l.equals("-")){
                    res = num1 - num2;
                }
                else if (l.equals("*")){
                    res = num1 * num2;
                }
                else if (l.equals("/")){
                    res = num1 / num2;
                }
                else {
                    throw new RuntimeException("Input error!!!");
                }
                stack.push(res + "");
            }
        }
        return Integer.parseInt(stack.pop());
    }
}

Infix to suffix

Suffixes are not easy to write, and infixes are easy to write

Specific steps:

  1. Initialize two stacks, operator stack s1 and stack s2 for storing intermediate results
  2. Scan infix expression from left to right
  3. Encountered operand, press it into s2
  4. Operator encountered, compare with s1 stack top operator priority
  • If s1 is empty or the operator at the top of the stack is an open bracket, this operator is directly put on the stack
  • Otherwise, if the priority is higher than the stack top operator, press the operator into s1
  • Otherwise, the s1 stack top operator pops up and is pushed into s2. Go to (4-1) again to compare with the new stack top operator in s1
  1. When parentheses are encountered:
  • If it is an open bracket, press in s1 directly
  • The right bracket pops up the s1 stack top operator at one time and pushes s2 until the left bracket is encountered. At this time, this pair of brackets is discarded
  1. Repeat steps 2-5 until the rightmost part of the expression
  2. Pop up the remaining operators in s1 and press them into s2 at one time
  3. Pop up the elements in s2 and output them at one time. The result is the corresponding expression of infix expression in reverse order
package com.fu.datastruct.stack;


import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class PolandNotation {
    public static void main(String[] args) {

        String e = "1+((2+3)*4)-5";//[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]

        List<String> infixExpressionList = toInfixExpressionList(e);
        System.out.println("Infix expression: "+infixExpressionList);
        List<String> suffixExpressionList = parseSuffixExpressionList(infixExpressionList);
        System.out.println("Postfix Expression : "+suffixExpressionList);
        System.out.println(calculate(suffixExpressionList));


    }
    public static List<String> parseSuffixExpressionList(List<String> ls){
        Stack<String> s1 = new Stack<>();
        List<String> s2 = new ArrayList<>();

        for (String item : ls) {
            if (item.matches("\\d+")){
                s2.add(item);
            }else if (item.equals("(")){
                s1.push(item);
            }else if (item.equals(")")){
                while (!s1.peek().equals("(")){
                    s2.add(s1.pop());
                }
                s1.pop();
            }else {
                while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)){
                    s2.add(s1.pop());
            }
            s1.push(item);}
        }
        while (s1.size()!=0)s2.add(s1.pop());
        return s2;
    }

    public static List<String> toInfixExpressionList(String s){
        List<String> ls = new ArrayList<>();
        int i = 0;
        String s1;
        char c ;
        do {
            if ((c = s.charAt(i))<48||(c = s.charAt(i))>57){
                ls.add("" + c);
                i++;
            }
            else {
                s1 = "";
                while (i < s.length() && (c=s.charAt(i))>=48 && (c=s.charAt(i))<=57){
                    s1 += c;
                    i++;
                }
                ls.add(s1);
            }
        } while(i < s.length());
        return ls;
    }


    //Complete the calculation of the inverse Polish expression
    public static int calculate(List<String> ls) {
        //To create a stack, you only need one stack
        Stack<String> stack = new Stack<>();
        for (String l : ls) {
            if (l.matches("\\d+")){
                stack.push(l);
            }
            else {
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if (l.equals("+")){
                    res = num1 + num2;
                }
                else if (l.equals("-")){
                    res = num1 - num2;
                }
                else if (l.equals("*")){
                    res = num1 * num2;
                }
                else if (l.equals("/")){
                    res = num1 / num2;
                }
                else {
                    throw new RuntimeException("Input error!!!");
                }
                stack.push(res + "");
            }
        }
        return Integer.parseInt(stack.pop());
    }
}
class Operation{
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIV = 2;
    public static int getValue(String operation){
        int result = 0;
        switch (operation){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
                break;
            default:
                System.out.println("The operator does not exist!!!");
                break;
        }
        return result;
    }
}

recursion

Recursive concept

Recursion means that the method calls itself and passes in different variables each time. Recursion helps programmers solve complex problems and makes the code more concise

Recursive compliance rules

  1. Execute a method to create a new protected independent space (stack space)
  2. Method local variables are independent and will not affect each other
  3. Method, the reference type is shared
  4. Recursion must approach the exit recursion condition, otherwise it will recurse infinitely, dead ghost
  5. When a method is executed or returned, the result will be returned to the person who calls it. When the method is executed or returned, the method is executed
package com.fu.recursion;

public class MiGong {
    public static void main(String[] args) {
        int[][] map = new int[8][7];
        for (int i = 0; i < 7; i++) {
            map[0][i] = 1;
            map[7][i] = 1;
        }//Up and down is 1
        for (int i = 0; i < 8; i++) {
            map[i][0] = 1;
            map[i][6] = 1;
        }//Left and right is 1
        map[3][1] = 1;
        map[3][2] = 1;//Baffle is 1
        System.out.println("Map situation:");
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 7; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
        setWay(map,1,1);

        System.out.println("The map of the ball passing by:");
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 7; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }


    }

    /**
     *
     * @param map Represent map
     * @param i Where do you start
     * @param j
     * @return If the path is found, it returns true; otherwise, it returns false
     * When the ball reaches map[6][5], it indicates that the path has been found
     * map[i][j]=0 It means that the point has not passed, 1 means the wall, 2 means it can go, and 3 means that the position has passed but can't go
     * When walking through the maze, you should determine a strategy, down - > right - > up - > left. If you can't get through this point, go back
     *
     *
     */
    public static boolean setWay(int[][]map,int i,int j){
        if(map[6][5] == 2){
            return true;
        }else {
            if (map[i][j] == 0){
                map[i][j] = 2;
                if (setWay(map,i+1,j)){
                    return true;
                }else if (setWay(map,i,j+1)){
                    return true;
                }else if (setWay(map,i-1,j)){
                    return true;
                }else if (setWay(map,i,j-1)){
                    return true;
                }else {
                    map[i][j] = 3;
                    return false;
                }
            }
            else {//map[i][j] != 0 //1 2 3
                return false;
            }
        }
    }
}

sort

Internal sorting

It refers to loading all data to be processed into internal memory (memory) for sorting

External sorting

The data is too large to be loaded into memory, so it needs to be sorted with the help of external storage

Common sorting algorithms

Direct insert sort

Shell Sort

Simple selection sort

Heap sort

Bubble sorting

Quick sort

Merge sort

Cardinality sort

Two methods to measure the execution time of a program (algorithm)

  1. Post execution method

feasible

However, to evaluate the performance of the design algorithm, it is necessary to actually run the program

The obtained time statistics depend on computer hardware, software and other environmental factors

This method needs to run in the same state on the same computer in order to compare which algorithm is faster

  1. Ex ante estimation method

The time complexity of a method is analyzed to determine which algorithm is better

Algorithm time complexity

Ignore constant term, ignore lower order term, ignore coefficient

Time frequency

The time spent by an algorithm is directly proportional to the number of statements executed. Which algorithm statement executes more times and takes more time. The number of statements executed by an algorithm is called statement frequency or time frequency

Replace all addition constants in the running time with constant 1

In the modified run times function, only the highest order item is retained

Remove the coefficient of the highest order term

Common time complexity

  1. Constant order O(1)
  2. Logarithmic order O(log 2 n)
  3. Linear order O(n)
  4. Linear logarithmic order O(nlog 2 n)
  5. Square order O(n^2)
  6. Cubic order O(n^3)
  7. K-th order O(n^k)
  8. Exponential order O(2^n)

The order of common time complexity from small to large: O (1) < o (NLog 2 n) < o (n ^ 2)

< o (N3) < o (NK) < o (2 ^ n). With the continuous increase of problem scale n, the above time complexity increases and the execution efficiency of the algorithm becomes low

We should avoid using exponential order algorithm

  1. Average time complexity refers to the running time of the algorithm when all possible input instances occur with equal probability

  2. The worst-case time complexity is called the worst-case time complexity. Generally speaking, the time complexity is the worst complexity

    Reason: in the worst case, the time complexity is the time limit of the algorithm running on any input instance, which ensures that the running time of the algorithm will not be longer than that in the worst case

Algorithm space complexity

  1. Similar to time complexity, algorithm space complexity is defined as the storage space consumed by the algorithm as a function of problem scale n
  2. Space complexity is a measure of the amount of storage space temporarily occupied by an algorithm during operation. The number of temporary work units occupied by some algorithms is related to the problem-solving scale n, which increases with the increase of N. n is larger and occupies more storage units
  3. Do algorithm analysis, mainly discuss the time complexity

Bubble sorting

In the sorting process, the elements are constantly close to their own position, and there is no exchange in one comparison, indicating that the sequence is orderly. Set a flag in the sorting to judge whether the elements have been exchanged, so as to reduce unnecessary comparison

rule

  1. Loop array size - 1 times
  2. The number of sorting per trip decreases gradually
  3. Optimization: if we find that there is no exchange in a certain sort, we can end the bubble sort in advance
package com.fu.sort;

import java.util.Arrays;

public class BubbleSort {
    public static void main(String[] args) {
        int a[] = {9,2,10,7,5,6,4,8,1,3};
        int temp;
        boolean flag = false;
        for (int i = 0; i < a.length-1; i++) {
            for (int j = 0; j < a.length-1-i; j++) {
                if (a[j]>a[j+1]){
                    flag = true;
                    temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
            if (!flag)break;
            else flag = false;
            System.out.println(Arrays.toString(a));
        }
    }
}

Select sort

Original array: 101,34119,1
First round sorting:
1,34,119,101
Second round sorting:
1,34,119,101
The third round of sorting:
1,34,101,119

explain:
1. Select a total array size for sorting - 1 round of sorting
2. Every round of sorting is another cycle, and the rules of the cycle (code)
2.1 first assume that the current number is the smallest
2.2 then compare with each subsequent number. If it is found that there is a smaller number than the current number,
The minimum number is determined again and the subscript is obtained
2.3 when you traverse to the end of the array, you will get the lowest decimal and subscript of this round
2.4 exchange [Code]

package com.fu.sort;

import java.util.Arrays;

public class SelectSort {
    public static void main(String[] args) {
        int a[] = {101,34,119,1};
         System.out.println(Arrays.toString(a));
        selectSort(a);
        System.out.println(Arrays.toString(a));
    }
    public static void selectSort(int[] arr){
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            int min = arr[i];
            for (int j = i + 1; j < arr.length; j++) {
                 if (min > arr[j]){
                    min = arr[j];
                    minIndex = j;
                }
            }
            if (minIndex != i){
                arr[minIndex] = arr[i];
                arr[i] = min;
            }
        }
    }
}

Insert sort

Insertional sorting belongs to internal sorting method, which is to find the element to be sorted by inserting
Appropriate position to achieve the purpose of sorting.

Thought:

The basic idea of Insertion Sorting is to treat n elements to be sorted as
An ordered table and an unordered table. At the beginning, the ordered table contains only one element. In the unordered table
It contains n-1 elements. In the sorting process, the first element is taken out of the unordered table every time, and it
The sorting code of is compared with the sorting code of the ordered table elements in turn, and it is inserted into the ordered table
Appropriate position to make it a new ordered table.

package com.fu.sort;

import java.util.Arrays;

public class InsertSort {
    public static void main(String[] args) {
        int []arr = {101,29,232,1};
        insertSort(arr);
        System.out.println(Arrays.toString(arr));

    }
    public static void insertSort(int []arr){
        for (int i = 0; i < arr.length-1; i++) {
            int insertVal = arr[i+1];
            int insertIndex = i;
            while (insertIndex >= 0 && insertVal < arr[insertIndex]){
                arr[insertIndex + 1] = arr[insertIndex];
                insertIndex--;
            }
            arr[insertIndex + 1] = insertVal;
        }
    }
}

Shell Sort

Introduction to Hill ranking method

Hill sorting is a sort algorithm proposed by Donald Shell in 1959. So is Hill ranking
An insertion sort, which is a more efficient version of simple insertion sort after improvement, also known as
Reduce incremental sort.

Basic idea of Hill ranking method

Hill sorting is to group the records according to a certain increment of subscript, and sort each group with direct insertion sorting algorithm;
As the increment decreases, each group contains more and more keywords. When the increment is reduced to 1, the whole file will be deleted
Divided into groups, the algorithm terminates

package com.fu.sort;

import java.util.Arrays;

/**
 * Hill sort moving method (optimization)
 */
public class ShellSort {
    public static void main(String[] args) {
        int []arr = {8,9,1,7,2,3,5,4,6,0};
        shellSort(arr);

    }
    public static void shellSort(int []arr){

        for (int gap = arr.length/2; gap > 0; gap/=2) {
            for (int i = gap; i < arr.length; i++) {
                int j = i;
                int temp = arr[j];
                if (arr[j] < arr[j-gap]){
                    while(j - gap >= 0 && temp < arr[j - gap]){
                        arr[j] = arr[j-gap];
                        j -= gap;
                    }
                    arr[j] = temp;
                }
            }
            System.out.println(Arrays.toString(arr));
        }
        }

    }


Quick sort

Quick sort( Quicksort)It is an improvement of bubble sorting. The basic idea is: sort by one trip
 Divide the data to be sorted into two separate parts, one of which has more data than the other
 All data should be small, and then quickly sort the two parts of data according to this method
 The sorting process can be carried out recursively, so that the whole data becomes an ordered sequence
package com.fu.sort;

import java.util.Arrays;

public class QuickSort {
    public static void main(String[] args) {
        int []arr = {-9,78,0,23,-567,70};
        quickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));

    }

    /**
     *
     * @param arr  Pass in array
     * @param left Left subscript
     * @param right Right subscript
     */
    public static void quickSort(int []arr,int left,int right){
        int l = left;
        int r = right;
        int pivot = arr[(left + right)/2];
        int temp = 0;
        //Loop to put the smaller value than pivot on the left and the larger value on the right
        while (l < r){
            //A value greater than or equal to pivot is found on the left of pivot
            while (arr[l]<pivot){
                l += 1;
            }
            //Find a value less than or equal to pivot on the right of pivot
            while (arr[r]>pivot){
                r -= 1;
            }
            if (l >= r){
                break;
            }
            //exchange
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            //After exchange, arr[l] == pivot value, equal --, move forward
            if (arr[l] == pivot){
                r -= 1;
            }
            //After exchange, arr[r] == pivot value, equal + +, move back
            if (arr[r] == pivot){
                l += 1;
            }

        }
        if (l == r){
            l += 1;
            r -= 1;
        }
        if (left < r){
            quickSort(arr,left,r);
        }
        if (right > l){
            quickSort(arr,l,right);
        }



    }
}

Merge sort

Merge sort( MERGE-SORT)It is a sorting method realized by using the idea of merging. The algorithm adopts the classic algorithm
 Divide and conquer( divide-and-conquer)Strategy (divide and conquer)(divide)Into small questions
 The problem is then solved recursively(conquer)The answer will be obtained in different stages"repair"stay
 Divide and rule). 
package com.fu.sort;

import java.util.Arrays;

public class MergerSort {
    public static void main(String[] args) {
        int arr[] = {8,4,5,7,1,3,6,2};
        int temp[] = new int[arr.length];
        mergeSort(arr,0 ,arr.length-1,temp);
        System.out.println(Arrays.toString(arr));
    }

    public static void mergeSort(int []arr,int left,int right,int[]temp ){
        if (left < right){
            int mid = (left + right)/2;
            mergeSort(arr,left,mid,temp);
            mergeSort(arr,mid+1,right,temp);
            merge(arr,left,mid,right,temp);
        }
    }
    /**
     *
     * @param arr  Sorted original array
     * @param left Left ordered sequence initial sequence
     * @param mid  Intermediate index
     * @param right Right index
     * @param temp Array for transit
     */
    public static void merge(int []arr ,int left ,int mid ,int right ,int []temp){
        int i = left;
        int j = mid + 1;
        int t = 0;
        while (i <= mid && j<=right){


        if (arr[i]<=arr[j]){
            temp[t] = arr[i];
            t+=1;
            i+=1;
        }else {
            temp[t] = arr[j];
            t+=1;
            j+=1;
        }
    }
        while(i <= mid){
            temp[t] = arr[i];
            t+=1;
            i+=1;
        }
        while(j <= right){
            temp[t] = arr[j];
            t+=1;
            j+=1;
        }
        //Copy temp array
        t = 0;
        int templeft = left;
        while(templeft <= right){
            arr[templeft] = temp[t];
            t+=1;
            templeft+=1;
        }

}
}

Cardinality sort (bucket sort)

introduce

  1. Cardinality sorting belongs to distributive sorting, also known as bucket method or bin sort. The elements to be sorted are allocated to the bucket through the value of each bit of the key value
  2. Cardinal ranking method belongs to stable ranking, and cardinal ranking method is a stable ranking method with high efficiency
  3. Cardinality sorting is an extension of bucket sorting
  4. Family sorting cuts the integer into different numbers according to the number of digits, and compares them respectively according to each number of digits

basic thought

  1. All comparison values shall be unified into the same digit length, and the number with short digits shall be filled with zero in front of it. Then, it shall be sorted in sequence from the lowest to the highest. After sorting from the lowest to the highest, the sequence will become an ordered sequence
package com.fu.sort;

import java.util.Arrays;

public class RadixSort {
    public static void main(String[] args) {
        int arr[] = {53, 3, 542, 748, 14, 214};
        radixSort(arr);

    }

    public static void radixSort(int[] arr) {
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i]>max){
                max = arr[i];
            }
        }
        int maxLength = (max + "").length();


        int[][] bucket = new int[10][arr.length];
        int[] bucketElementCounts = new int[10];

        for (int i = 0,n=1; i < maxLength; i++,n*=10) {
            for (int j = 0; j < arr.length; j++) {
                int digitOfElement = arr[j] /n % 10;
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
                bucketElementCounts[digitOfElement]++;
            }
            int index = 0;
            for (int k = 0; k < bucketElementCounts.length; k++) {
                if (bucketElementCounts[k] != 0){
                    for (int l = 0; l < bucketElementCounts[k]; l++) {
                        arr[index++] = bucket[k][l];
                    }
                }
                bucketElementCounts[k] = 0;
            }
            System.out.println(Arrays.toString(arr));
        }
        
    }
}

Comparison and summary of common sorting algorithms

  1. stable
  2. instable
  3. Inner sorting
  4. External sorting
  5. Time complexity
  6. Spatial complexity
  7. Data scale
  8. Number of barrels
  9. No extra memory
  10. Occupy additional memory

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ytf671hd-1643456651036) (C: \ users \ 11021 \ appdata \ roaming \ typora \ typora user images \ 1643267909953. PNG)]

lookup

Common search in java:

  1. Sequential (linear) lookup
  2. Binary search / half search
  3. Interpolation search
  4. Fibonacci search (golden section point search)

Sequential (linear) lookup

The simplest way to find is to find from beginning to end

package com.fu.search;

public class SeqSearch {
    public static void main(String[] args) {
        int arr[] = {1,9,11,-1,34,89};
        int index = seqSearch(arr,11);
        if (index == -1){
            System.out.println("Can't find");
        }else {
            System.out.println("Found, subscript:"+ index);
        }
    }

    /**
     *
     * @param arr 
     * @param value
     * @return
     */
    public static int seqSearch(int []arr,int value){
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value){
                return i;
            }
        }
        return -1;
    }
}

Binary search

Idea:

  1. 1. First, determine the middle subscript of the array
    2. Then compare the numbers you need to find
    3. The number to find is mid Left, recursive right lookup
    4. The number to find is mid Right, recursive left search
    5. Return when found and end recursion
    6. Recursion complete array, still not found, also want to end recursion
    
package com.fu.search;

//Binary lookup array must be ordered
public class BinarySearch {
    public static void main(String[] args) {
        int arr[] = {1, 8, 10, 89, 1000, 1234};
        System.out.println(binarySearch(arr, 0, arr.length - 1, 88));
    }
    /**
     *
     * @param arr array
     * @param left Left index
     * @param right Right index
     * @param findVal Value to find
     * @return Return subscript found, return - 1 not found
     */
    public static int binarySearch(int []arr,int left,int right,int findVal){
        int mid = (left + right)/2;
        int midVal = arr[mid];

        if (left> right){return  -1;}
        if (findVal > midVal){
            return binarySearch(arr,mid + 1,right,findVal);
        }
        else if (findVal < midVal){
            return binarySearch(arr,left,mid-1,findVal);
        }else {
            return mid;
        }

    }
}

Interpolation search

  1. Interpolation search is similar to binary search, except that interpolation search starts from adaptive mid each time
  2. int midIndex = low + (high - low)*(key - arr[low])/(arr[high] - arr[low])\
package com.fu.search;

import java.util.Arrays;

public class InsertSearch {
    public static void main(String[] args) {
        int []arr = new int[100];
        for (int i = 0; i < 100; i++) {
            arr[i] = i+1;
        }
        System.out.println(insertValueSearch(arr, 0, arr.length-1, 9));
    }

    /**
     * Interpolation lookup requires an ordered array
     * @param arr array
     * @param left Left index
     * @param right Right index
     * @param findVal Find value
     * @return
     */
    public static int insertValueSearch(int []arr,int left,int right,int findVal){
        if(left > right || findVal < arr[0] || findVal > arr[arr.length-1]){
            return -1;
        }
        int mid = left + (right - left) * (findVal - arr[left])/(arr[right] - arr[left]);
        int midVal = arr[mid];
        if (findVal > midVal){//Description should recurse to the right
            return insertValueSearch(arr,mid+1,right,findVal);
        } else if (findVal<midVal){//Description should recurse to the left
            return insertValueSearch(arr,left,mid-1,findVal);
        } else {
            return mid;
        }
    }
}

Fiboracci find 0.168

The golden section point value divides a line segment into two parts. The ratio of one part to the whole length is equal to the ratio of the other part to this part

Take the first three digits as the approximate value of 0.618. Because the shape designed according to this ratio is very beautiful, it has become the golden section, which is called the Chinese foreign ratio. It is a magical number and brings unexpected results

Fibonacci sequence {1, 1, 2, 3, 5, 8, 13, 21, 34, 55} it is found that the ratio of two adjacent numbers in Fibonacci sequence is infinitely close to the golden section value of 0.168

package com.fu.search;

import java.util.Arrays;

public class FibonacciSearch {
    public static int maxSize = 20;
    public static void main(String[] args) {
        int []arr = {1,8,10,89,1000,1234};
        System.out.println(fibSearch(arr,1));
    }
    //Get a fiboracci sequence
    public static int[] fib(){
        int []f = new int [maxSize];
        f[0] = 1;
        f[1] = 1;
        for (int i = 2; i < maxSize; i++) {
            f[i] = f[i-1] + f[i-2];
        }
        return f;
    }

    /**
     *
     * @param a array
     * @param key Key required
     * @return Return corresponding subscript / - 1
     */
    public static int fibSearch(int [] a,int key){
        int low = 0;
        int high = a.length - 1;
        int k = 0;
        int mid = 0;
        int f[] = fib();//Get fiboracci sequence
        //Get fiboracci sequence subscript
        while (high > f[k]-1){
            k++;
        }
        int []temp = Arrays.copyOf(a,f[k]);
        for (int i = high+1; i < temp.length; i++) {
            temp[i] = a[high];
        }
        while(low <= high){
            mid = low + f[k-1] -1;
            if (key < temp[mid]){
                high = mid - 1;
                k--;
            }
            else if (key > temp[mid]){
                low = mid + 1;
                k -= 2;
            }else {
                if (mid <= high){
                    return mid;
                }else {
                    return high;
                }
            }

        }return -1;





    }

}

Hashtable

Hash table, also known as hash table, directly accesses the data structure according to the key value, that is, the key is mapped to a position in the table to access records and speed up the search speed. This mapping function is called hash function, and the storage record array is hash

Hash table structure:

Array + linked list

Array + binary tree

Basic introduction

Hash table is a data structure that can be accessed directly according to the key value, that is, by mapping the key value to a position in the table to access records and speed up the search. This mapping function is called hash function, and the array storing records is called Hash list

package com.fu.hashtab;
import java.util.Scanner;

public class HashTabDemo {
    public static void main(String[] args) {
        HashTab hashTab = new HashTab(10);
        String key = "";
        Scanner scanner = new Scanner(System.in);
        while(true) {
            System.out.println("add Add employee");
            System.out.println("list Show employees");
            System.out.println("find Find employees");
            System.out.println("exit Exit the system");
            key = scanner.next();
            switch (key){
                case "add":
                    System.out.println("input id");
                    int id = scanner.nextInt();
                    System.out.println("Enter name");
                    String name = scanner.next();
                    Emp emp = new Emp(id, name);
                    hashTab.add(emp);
                    break;
                case "list":
                    hashTab.list();
                    break;
                case "find":
                    System.out.println("Enter the to find id");
                    id = scanner.nextInt();
                    hashTab.findEmpById(id);
                    break;
                case "exit":
                    scanner.close();
                    System.exit(0);
                default:
                    break;
            }
        }
    }
}
class Emp{
    public int id;
    public String name;
    public Emp next;//The default is empty

    public Emp(int id, String name) {
        this.id = id;
        this.name = name;
    }
}
class HashTab{
    private EmpLinkedList[] empLinkedListArray;
    private int size;
    public HashTab(int size) {
        this.size = size;
        empLinkedListArray = new EmpLinkedList[size];
        //Initialize each linked list
        for (int i = 0; i < size; i++) {
            empLinkedListArray[i] = new EmpLinkedList();
        }
    }
    public void add(Emp emp){
        int empLinkedListNO = hashFun(emp.id);
        empLinkedListArray[empLinkedListNO].add(emp);
    }
    public int hashFun(int id){
        return id % size;
    }
    public void list(){//Traversal hash table
        for (int i = 0; i < size; i++) {
            empLinkedListArray[i].list(i);
        }
    }
    public void findEmpById(int id){
        int empLinkedListNO = hashFun(id);
        Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);
        if (emp != null){
            System.out.printf("stay%d Employee found in linked list id = %d\n",(empLinkedListNO + 1),id);
        }else{
            System.out.println("The employee was not found in the hash table");
        }
    }

}
class EmpLinkedList{
    private Emp head;
    //add to
    public void add(Emp emp){
        if (head == null){
            head = emp;
            return;
        }
        Emp curEmp = head;
        while (true){
            if (curEmp.next == null){
                break;
            }
            curEmp = curEmp.next;
        }
        curEmp.next = emp;
    }
    //ergodic
    public void list(int no){
        if (head == null){
            System.out.println("The first"+(no+1)+"The current linked list is empty");
            return;
        }
        System.out.println("The first"+(no+1)+"The linked list information is:");
        Emp curEmp = head;
        while(true){
            System.out.printf("=> id = %d name = %s\t",curEmp.id,curEmp.name);
            if (curEmp.next == null){
                break;
            }
            curEmp=curEmp.next;
        }
        System.out.println();
    }
    public Emp findEmpById(int id){
        if (head == null){
            System.out.println("The linked list is empty");
        }
        Emp curEmp = head ;
        while (true){
            if (curEmp.id == id){
                break;
            }
            if (curEmp.next == null){
                curEmp = null;
            }
            curEmp = curEmp.next;
        }
        return curEmp;

    }

}

tree

Tree vs array vs linked list

The insertion and deletion efficiency of array is low

The search efficiency of linked list is low

The number ensures the speed of each item

Binary tree

  1. There are many kinds of trees, and each node has at most two child nodes. One form is called binary tree
  2. The child nodes of binary tree include left node and right node
  3. All leaf nodes of the binary tree are in the last layer, and the total number of nodes is 2^n-1, that is, the full binary tree
  4. If all leaf nodes of a binary tree are in the last or penultimate layer, the leaf nodes of the last layer are continuous to the left and the leaf nodes of the penultimate layer are continuous to the right, it is called a full binary tree

Traversal of tree

Create a binary tree

Preorder traversal:

First output the parent node, and then traverse the left and right subtrees

If the left child node is not empty, the previous traversal will continue recursively

If the right child node is not empty, recursively continue the preorder traversal

Middle order traversal:

Traverse the parent tree, and then output the child tree to the left

If the left child node of the current node is not empty, it will be traversed in recursive order

Output current node

If the right child node of the current node is not empty, it will be traversed in recursive order

Post order traversal:

First traverse the left and right subtrees, and then output the parent node

Look at the order of the output parent nodes and determine the pre order and post order

If the left child node of the current node is not empty, it will be traversed recursively

If the right child node of the current node is not empty, it will be traversed in recursive order

Output current node

Common terms for trees:

  1. node
  2. Root node
  3. Parent node
  4. Child node
  5. Leaf node (node without child nodes)
  6. Weight of node (node value)
  7. Path (find the route of the node from the root node)
  8. layer
  9. subtree
  10. Height of the tree (maximum number of layers)
  11. Forest (forest composed of several sub trees)
package com.fu.tree;

public class BinaryTreeDemo {
    public static void main(String[] args) {
        //Create a binary tree
        BinaryTree binaryTree = new BinaryTree();
        HeroNode root = new HeroNode(1, "Song Jiang");
        HeroNode node2 = new HeroNode(2, "Wu Yong");
        HeroNode node3 = new HeroNode(3, "Lu Junyi");
        HeroNode node4 = new HeroNode(4, "Lin Chong");

        //Manually create a binary tree, and then create it recursively
        root.setLeft(node2);
        root.setRight(node3);
        node3.setRight(node4);

        System.out.println("Preorder traversal");
        binaryTree.setRoot(root);
        binaryTree.preOrder();
        System.out.println("Postorder traversal");
        binaryTree.infixOrder();
        System.out.println("Middle order traversal");
        binaryTree.postOrder();
        



    }
}
class BinaryTree{
    private HeroNode root;

    public void setRoot(HeroNode root) {
        this.root = root;
    }
    //Preorder traversal
    public void preOrder(){
        if (this.root != null){
            this.root.preOrder();
        }
        else {
            System.out.println("Binary tree is empty and cannot be traversed");
        }
    }

    //Middle order traversal
    public void infixOrder(){
        if (this.root != null){
            this.root.infixOrder();
        }
        else {
            System.out.println("Binary tree is empty and cannot be traversed");
        }
    }
    //Postorder traversal
    public void postOrder(){
        if (this.root != null){
            this.root.postOrder();
        }else {
            System.out.println("Binary tree is empty and cannot be traversed");
        }
    }

}


class HeroNode{
    private int no;
    private String name;
    private HeroNode left;
    private HeroNode right;

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

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

    public HeroNode getRight() {
        return right;
    }

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

    @Override
    public String toString() {
        return "HeroNode[" +
                "no=" + no +
                ", name='" + name + '\'' +
                ']';
    }

    //Preorder traversal
     public void preOrder(){
         System.out.println(this);
         //Recursive pre order traversal to the left subtree
         if (this.left != null){
             this.left.preOrder();
         }
         //Recursive right subtree preorder traversal
         if (this.right != null){
             this.right.preOrder();
         }
     }

    //Middle order traversal
    public void infixOrder(){
        //Recursive traversal to the middle order of the left subtree
        if (this.left != null){
            this.left.infixOrder();
        }
        //Output parent node
        System.out.println(this);
        //Recursive traversal in right subtree
        if (this.right != null){
            this.right.infixOrder();
        }

    }
    //Postorder traversal
    public void postOrder(){
        if (this.left != null){
            this.left.postOrder();
        }
        if (this.right != null){
            this.right.postOrder();
        }
        System.out.println(this);
    }



}

Binary tree lookup

  1. Pre order search, middle order search and post order search methods
  2. Three search methods are used to find the node with heroNO=5
  3. Analyze various search methods and compare them for how many times

Pre order search ideas:

  1. Judge whether the current node no is equal to the node to be searched
  2. If equal, the current node is returned
  3. Unequal. Judge whether the current node is empty. If it is not empty, recursive preorder search
  4. Left recursive preorder search, find the node and return. Otherwise, continue to judge whether the right node of the current node is empty. If not, continue to right recursive preorder search

Middle order search idea

  1. Judge whether the left child node of the current node is empty. If it is not empty, search in recursive middle order
  2. If it is found, it will be returned. If it is not found, it will be compared with the current node. If it is yes, it will be returned to the current node. Otherwise, it will continue to search in the middle order of right recursion
  3. There is recursive middle order search. If it is found, it will be returned. Otherwise, it will be null

Post order search idea

  1. Judge whether the left child node of the current node is empty. If it is not empty, recursive subsequent search
  2. If found, return. If not found, judge whether the right child node of the current node is empty. If not, there is recursive subsequent search. If found, return
  3. And the current node, return, otherwise null
package com.fu.tree;

public class BinaryTreeDemo {
    public static void main(String[] args) {
        //Create a binary tree
        BinaryTree binaryTree = new BinaryTree();
        HeroNode root = new HeroNode(1, "Song Jiang");
        HeroNode node2 = new HeroNode(2, "Wu Yong");
        HeroNode node3 = new HeroNode(3, "Lu Junyi");
        HeroNode node4 = new HeroNode(4, "Lin Chong");

        //Manually create a binary tree, and then create it recursively
        root.setLeft(node2);
        root.setRight(node3);
        node3.setRight(node4);

        System.out.println("Preorder traversal");
        binaryTree.setRoot(root);
        binaryTree.preOrder();
        System.out.println("Postorder traversal");
        binaryTree.infixOrder();
        System.out.println("Middle order traversal");
        binaryTree.postOrder();

        HeroNode resNode = binaryTree.preOrderSearch(4);
        if (resNode != null){
            System.out.printf("Yes, information no=%d name=%s",resNode.getNo(),resNode.getName());
        }else {
            System.out.printf("Can't find no = %d Hero of",5);
        }



    }
}
class BinaryTree{
    private HeroNode root;

    public void setRoot(HeroNode root) {
        this.root = root;
    }
    //Preorder traversal
    public void preOrder(){
        if (this.root != null){
            this.root.preOrder();
        }
        else {
            System.out.println("Binary tree is empty and cannot be traversed");
        }
    }

    //Middle order traversal
    public void infixOrder(){
        if (this.root != null){
            this.root.infixOrder();
        }
        else {
            System.out.println("Binary tree is empty and cannot be traversed");
        }
    }
    //Postorder traversal
    public void postOrder(){
        if (this.root != null){
            this.root.postOrder();
        }else {
            System.out.println("Binary tree is empty and cannot be traversed");
        }
    }
    //Preorder search
    public HeroNode preOrderSearch(int no){
        if (root != null){
            return root.postOrderSearch(no);
        }else {
            return null;
        }
    }
    //Medium order search
    public HeroNode infixOrderSearch(int no){
        if (root != null){
            return root.preOrderSearch(no);
        }else {
            return null;
        }
    }
    //Postorder traversal
    public HeroNode postOrderSearch(int no) {
        if (root != null) {
            return root.postOrderSearch(no);
        }else {
            return null;
        }


    }
}


class HeroNode{
    private int no;
    private String name;
    private HeroNode left;
    private HeroNode right;

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

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

    public HeroNode getRight() {
        return right;
    }

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

    @Override
    public String toString() {
        return "HeroNode[" +
                "no=" + no +
                ", name='" + name + '\'' +
                ']';
    }

    //Preorder traversal
     public void preOrder(){
         System.out.println(this);
         //Recursive pre order traversal to the left subtree
         if (this.left != null){
             this.left.preOrder();
         }
         //Recursive right subtree preorder traversal
         if (this.right != null){
             this.right.preOrder();
         }
     }

    //Middle order traversal
    public void infixOrder(){
        //Recursive traversal to the middle order of the left subtree
        if (this.left != null){
            this.left.infixOrder();
        }
        //Output parent node
        System.out.println(this);
        //Recursive traversal in right subtree
        if (this.right != null){
            this.right.infixOrder();
        }

    }
    //Postorder traversal
    public void postOrder(){
        if (this.left != null){
            this.left.postOrder();
        }
        if (this.right != null){
            this.right.postOrder();
        }
        System.out.println(this);
    }

    //Preorder search

    /**
     *
     * @param no Find no
     * @return Return Node found, return null if not found
     */
    public HeroNode preOrderSearch(int no){
        if (this.no == no){
            return this;
        }
        HeroNode resNode = null;
        if (this.left != null){
          resNode =   this.left.preOrderSearch(no);
        }
        if(resNode != null){
         return resNode;
        }
        if (this.right != null){
                resNode = this.right.preOrderSearch(no);
        }
        return resNode;
    }
    //Middle order traversal
    public HeroNode infixOrderSearch(int no){
        HeroNode resNode = null;
        if (this.left != null){
            resNode = this.left.infixOrderSearch(no);
        }
        if (resNode != null){
            return resNode;
        }
        if (this.no == no){
            return this;
        }
        if (this.right != null){
            resNode = this.right.infixOrderSearch(no);
        }
        return resNode;
    }
    //after
    public HeroNode postOrderSearch(int no){
        HeroNode resNode = null;
        if (this.left != null){
            resNode = this.left.postOrderSearch(no);
        }
        if (resNode != null){
            return resNode;
        }
        if (this.right != null){
            resNode =this.right.postOrderSearch(no);
        }
        if (resNode != null){
            return resNode;
        }
        if (this.no == no){
            return this;
        }
        return resNode;
    }

}

Delete node from binary tree

  1. Delete node is a leaf node. Delete this node
  2. If the deleted node is a non leaf node, delete the subtree

Idea:

  1. If the tree is an empty tree with only one root node, it is equivalent to setting the binary tree empty

  2. Our binary tree is unidirectional, so we can judge whether the child nodes of the current node need to delete nodes. We can't judge whether this node needs to delete nodes

  3. If the left child node of the current node is not empty and the left child node is the node to be deleted, set this Left = null and returns (end recursive deletion)

  4. If the right child node of the current node is not empty, and the right child node is the node to be deleted, this Right = null and returns (end recursive deletion)

  5. If the node is not deleted in the second and third steps, we need to delete it recursively to the left subtree

  6. Step 4: if the node is not deleted, the right subtree of the row should be deleted recursively

    package com.fu.tree;
    
    public class BinaryTreeDemo {
        public static void main(String[] args) {
            //Create a binary tree
            BinaryTree binaryTree = new BinaryTree();
            HeroNode root = new HeroNode( 1, "Song Jiang");
            HeroNode node2 = new HeroNode(2, "Wu Yong");
            HeroNode node3 = new HeroNode(3, "Lu Junyi");
            HeroNode node4 = new HeroNode(4, "Lin Chong");
    
            //Manually create a binary tree, and then create it recursively
            root.setLeft(node2);
            root.setRight(node3);
            node3.setRight(node4);
    
            System.out.println("Preorder traversal");
            binaryTree.setRoot(root);
            binaryTree.preOrder();
            System.out.println("Postorder traversal");
            binaryTree.infixOrder();
            System.out.println("Middle order traversal");
            binaryTree.postOrder();
    
            HeroNode resNode = binaryTree.preOrderSearch(4);
            if (resNode != null){
                System.out.printf("Yes, information no=%d name=%s",resNode.getNo(),resNode.getName());
            }else {
                System.out.printf("Can't find no = %d Hero of",5);
            }
            System.out.println("Before deletion,Preorder traversal~~~");
            binaryTree.preOrder();
            binaryTree.delNode(5);
            System.out.println("After deletion,Preorder traversal~~~");
            binaryTree.preOrder();
    
        }
    }
    class BinaryTree{
        private HeroNode root;
    
        public void setRoot(HeroNode root) {
            this.root = root;
        }
        //Delete node
        public void delNode(int no){
            if (root != null){
                if (root.getNo() == no){
                    root = null;
                }else {
                    root.delNode(no);
                }
            }else {
                System.out.println("Empty number cannot be deleted");
            }
        }
        //Preorder traversal
        public void preOrder(){
            if (this.root != null){
                this.root.preOrder();
            }
            else {
                System.out.println("Binary tree is empty and cannot be traversed");
            }
        }
    
        //Middle order traversal
        public void infixOrder(){
            if (this.root != null){
                this.root.infixOrder();
            }
            else {
                System.out.println("Binary tree is empty and cannot be traversed");
            }
        }
        //Postorder traversal
        public void postOrder(){
            if (this.root != null){
                this.root.postOrder();
            }else {
                System.out.println("Binary tree is empty and cannot be traversed");
            }
        }
        //Preorder search
        public HeroNode preOrderSearch(int no){
            if (root != null){
                return root.postOrderSearch(no);
            }else {
                return null;
            }
        }
        //Medium order search
        public HeroNode infixOrderSearch(int no){
            if (root != null){
                return root.preOrderSearch(no);
            }else {
                return null;
            }
        }
        //Postorder traversal
        public HeroNode postOrderSearch(int no) {
            if (root != null) {
                return root.postOrderSearch(no);
            }else {
                return null;
            }
    
    
        }
    }
    
    
    class HeroNode{
        private int no;
        private String name;
        private HeroNode left;
        private HeroNode right;
    
        public HeroNode(int no, String name) {
            this.no = no;
            this.name = name;
        }
    
        public int getNo() {
            return no;
        }
    
        public void setNo(int no) {
            this.no = no;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public HeroNode getLeft() {
            return left;
        }
    
        public void setLeft(HeroNode left) {
            this.left = left;
        }
    
        public HeroNode getRight() {
            return right;
        }
    
        public void setRight(HeroNode right) {
            this.right = right;
        }
    
        @Override
        public String toString() {
            return "HeroNode[" +
                    "no=" + no +
                    ", name='" + name + '\'' +
                    ']';
        }
        //Recursively delete nodes
        public void delNode(int no){
            if (this.left != null && this.left.no == no){
                this.left = null;
                return;
            }
            if (this.right != null && this.right.no == no){
                this.right = null;
                return;
            }
            if (this.left != null){
                this.left.delNode(no);
            }
            if (this.right != null){
                this.right.delNode(no);
            }
    
        }
    
        //Preorder traversal
         public void preOrder(){
             System.out.println(this);
             //Recursive pre order traversal to the left subtree
             if (this.left != null){
                 this.left.preOrder();
             }
             //Recursive right subtree preorder traversal
             if (this.right != null){
                 this.right.preOrder();
             }
         }
    
        //Middle order traversal
        public void infixOrder(){
            //Recursive traversal to the middle order of the left subtree
            if (this.left != null){
                this.left.infixOrder();
            }
            //Output parent node
            System.out.println(this);
            //Recursive traversal in right subtree
            if (this.right != null){
                this.right.infixOrder();
            }
    
        }
        //Postorder traversal
        public void postOrder(){
            if (this.left != null){
                this.left.postOrder();
            }
            if (this.right != null){
                this.right.postOrder();
            }
            System.out.println(this);
        }
    
        //Preorder search
    
        /**
         *
         * @param no Find no
         * @return Return Node found, return null if not found
         */
        public HeroNode preOrderSearch(int no){
            if (this.no == no){
                return this;
            }
            HeroNode resNode = null;
            if (this.left != null){
              resNode =   this.left.preOrderSearch(no);
            }
            if(resNode != null){
             return resNode;
            }
            if (this.right != null){
                    resNode = this.right.preOrderSearch(no);
            }
            return resNode;
        }
        //Middle order traversal
        public HeroNode infixOrderSearch(int no){
            HeroNode resNode = null;
            if (this.left != null){
                resNode = this.left.infixOrderSearch(no);
            }
            if (resNode != null){
                return resNode;
            }
            if (this.no == no){
                return this;
            }
            if (this.right != null){
                resNode = this.right.infixOrderSearch(no);
            }
            return resNode;
        }
        //after
        public HeroNode postOrderSearch(int no){
            HeroNode resNode = null;
            if (this.left != null){
                resNode = this.left.postOrderSearch(no);
            }
            if (resNode != null){
                return resNode;
            }
            if (this.right != null){
                resNode =this.right.postOrderSearch(no);
            }
            if (resNode != null){
                return resNode;
            }
            if (this.no == no){
                return this;
            }
            return resNode;
        }
    
    }
    
    

!= null){
this.left.delNode(no);
}
if (this.right != null){
this.right.delNode(no);
}

   }

   //Preorder traversal
    public void preOrder(){
        System.out.println(this);
        //Recursive pre order traversal to the left subtree
        if (this.left != null){
            this.left.preOrder();
        }
        //Recursive right subtree preorder traversal
        if (this.right != null){
            this.right.preOrder();
        }
    }

   //Middle order traversal
   public void infixOrder(){
       //Recursive traversal to the middle order of the left subtree
       if (this.left != null){
           this.left.infixOrder();
       }
       //Output parent node
       System.out.println(this);
       //Recursive traversal in right subtree
       if (this.right != null){
           this.right.infixOrder();
       }

   }
   //Postorder traversal
   public void postOrder(){
       if (this.left != null){
           this.left.postOrder();
       }
       if (this.right != null){
           this.right.postOrder();
       }
       System.out.println(this);
   }

   //Preorder search

   /**
    *
    * @param no Find no
    * @return Returned Node found, null returned if not found
    */
   public HeroNode preOrderSearch(int no){
       if (this.no == no){
           return this;
       }
       HeroNode resNode = null;
       if (this.left != null){
         resNode =   this.left.preOrderSearch(no);
       }
       if(resNode != null){
        return resNode;
       }
       if (this.right != null){
               resNode = this.right.preOrderSearch(no);
       }
       return resNode;
   }
   //Middle order traversal
   public HeroNode infixOrderSearch(int no){
       HeroNode resNode = null;
       if (this.left != null){
           resNode = this.left.infixOrderSearch(no);
       }
       if (resNode != null){
           return resNode;
       }
       if (this.no == no){
           return this;
       }
       if (this.right != null){
           resNode = this.right.infixOrderSearch(no);
       }
       return resNode;
   }
   //after
   public HeroNode postOrderSearch(int no){
       HeroNode resNode = null;
       if (this.left != null){
           resNode = this.left.postOrderSearch(no);
       }
       if (resNode != null){
           return resNode;
       }
       if (this.right != null){
           resNode =this.right.postOrderSearch(no);
       }
       if (resNode != null){
           return resNode;
       }
       if (this.no == no){
           return this;
       }
       return resNode;
   }

}



Topics: Algorithm data structure linked list