Java data structure -- linked list and stack

Keywords: Java data structure linked list

Introduction to linked list

Is an ordered list, but memory is stored differently as follows:

  • It is stored as a node

  • Each node contains a data field to store data, and the next field points to the next node

  • Each node is not necessarily stored continuously

  • The linked list is divided into the linked list of the leading node and the linked list of the non leading node

Single linked list

  • The next field of the last node is null, indicating the end

Application example of single linked list: ranking of heroes of the marsh (addition, deletion, modification and query)

Add ideas:

Add idea 2:

Modification idea:

  • Directly find the node to be modified and modify it directly

Delete idea:

code:

 //Deletion of nodes by number
    public void del(int no){
        //Find the previous node of the node to be deleted through the temporary variable
        HeroNode temp = head;
        boolean flag = false;

        while(true){
            if(temp.next == null){
                System.out.print("No nodes were found to delete,");
                break;
            }

            if(temp.next.no==no){
                flag = true;
                break;
            }

            temp = temp.next;
        }

        if(flag){
            temp.next = temp.next.next;
            System.out.println("Delete succeeded");
        }else{
            System.out.println("Deletion failed");
            System.out.printf("You want to delete%d Node does not exist\n",no);
        }
    }

One way linked list topic


1) Get the valid number of nodes

    public static int getLength(HeroNode head){
        //Do not count header nodes
        if(head.next == null){
            return 0;
        }
        int length = 0;
        HeroNode cur = head.next;
        while(cur!=null){
            length++;
            cur = cur.next;
        }

        return length;
    }

2) Find the penultimate node in the single lin k ed list

1. Write a method to receive the head node and an index at the same time
2.index indicates the penultimate node
3. Traverse the linked list from beginning to end to get the total length of the linked list
4. After getting the size, we traverse the size index

    public static HeroNode findLastIndexNode(HeroNode head ,int index ){
        if(head.next == null){
            System.out.println("Can't find");
            return null;
        }

        int size = getLength(head);
        //Verification of data
        if(index<=0||index>size){
            return null;
        }
        //for locate where you want to find it
        HeroNode cur = head.next;
        for (int i = 0; i < size-index; i++) {
            cur = cur.next;
        }

        return cur;
    }

3) Inversion of single linked list

1. First define a node reverseHead = new HeroNode();
2. Traverse the original linked list from beginning to end. Every time you traverse a node, this node will be picked and placed at the front of the new linked list reverseLinkedList
3. The original linked list head.next = reverseHead.next
The idea is to change the direction of each node to become the second node of the new chain header node, and finally directly point the original chain header node to the new chain list

public static void reverseList(HeroNode head){
        //If the current list is empty or there is only one node, there is no need to reverse
        if(head.next==null|| head.next.next == null){
            System.out.println("No inversion required");
            return;
        }
        //Define an auxiliary variable to help us traverse the original linked list
        HeroNode cur = head.next;
        HeroNode next = null;//Points to the next node of the current node [cur]
        HeroNode reverseHead = new HeroNode(0,"","");//The head node of the new linked list
        //Traverse the original linked list, take out each node and put it at the front of the reverseList
        //Personal experience: in fact, when traversing each node, we turn the next point of each node into the next node of the new chain header node
        while(cur!=null){
            next = cur.next;//Save the next node temporarily
            cur.next = reverseHead.next;//Update the location pointed to by this node
            reverseHead.next = cur;//Connect this node to the new header
            cur = next;
        }
        //Point head.next to reverseHead.next
        head.next = reverseHead.next;
    }

4) Print the single linked list from end to end (reverse traversal uses stack stack stack)

1. Reverse printing destroys the structure and is not recommended
2. Use stack

public static void reversePrint(HeroNode head){
        if(head.next==null){
            System.out.println("Empty linked list");
            return;
        }

        Stack<HeroNode> stack = new Stack<>();
        HeroNode cur = head.next;

        while(cur!=null){
            stack.push(cur);
            cur = cur.next;
        }

        while(stack.size()>0){
            System.out.println(stack.pop().toString());
        }
    }

5) Merge two ordered linked lists, and then they are still ordered

public static Node mergeTwoList2(Node head1, Node head2) {
        //In the case of a null linked list, if head1 is not equal to null, head1 is returned; otherwise, head2 is returned
        if (head1 == null || head2 == null) {
            return head1 != null ? head1 : head2;
        }

        //After merging, select small data as the header node of the single chain header node (specify that the new linked list is sorted from large to small)
        Node head = head1.data < head2.data ? head1 : head2;
        //cur1 represents the temporary variable of the new header node
        Node cur1 = head == head1 ? head1 : head2;
        //cur2 represents the head node of another linked list that is not used as the head node
        Node cur2 = head == head1 ? head2 : head1;

        Node pre = null;//cur1 previous element
        Node next = null;//The last element of cur2

        while (cur1 != null && cur2 != null) {
            //You must come here for the first time
            if (cur1.data <= cur2.data) {
                pre = cur1;
                cur1 = cur1.next;
            } else {
                next = cur2.next;
                pre.next = cur2;
                cur2.next = cur1;
                pre = cur2;
                cur2 = next;
            }
        }
        pre.next = cur1 == null ? cur2 : cur1;
        return head;
    }

Bidirectional linked list

Add ideas:

Modification idea:

  • It is the same as the original one-way linked list

Delete idea:

Unidirectional ring linked list

Application case: Joseph Ring problem

Creation idea:

Idea of traversing circular linked list:

Solution to the problem:

code:

public class _josephus problem _ {
    public static void main(String[] args) {
        CircleSingleList circleSingleList = new CircleSingleList();
        circleSingleList.addBoy(5);
        circleSingleList.showBoy();

        circleSingleList.countBoy(1,2);
    }
}


class CircleSingleList{
    //The first node currently has no number
    private boyNode first = null;

    public void  addBoy(int nums){
        //nums does a data check
        if(nums<1){
            System.out.println("nums The value of is incorrect");
            return;
        }
        boyNode curBoy = null;//Auxiliary pointer to build a ring linked list

        //Use for to create a circular linked list
        for (int i = 1; i <= nums; i++) {
            boyNode boy = new boyNode(i);
            if(i==1){
                first = boy;
                first.setNext(first);
                curBoy = first;
            }else{
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }
    }

    public void showBoy(){
        if(first == null){
            System.out.println("There are no children");
            return;
        }
        //Auxiliary pointer to complete the traversal
        boyNode curBoy = first;
        while (true) {
            System.out.println("The child's number is:"+curBoy.getNo());
            if(curBoy.getNext() == first){
                break;
            }
            curBoy = curBoy.getNext();
        }


    }

    //Generate a child out of circle sequence according to the specified k m

    /**
     *
     * @param startNum It means counting from the first child
     * @param countNum It means counting
     */
    public void countBoy(int startNum,int countNum){
        // Verify the data first
        if(first==null||startNum<1){
            System.out.println("Incorrect parameter input");
            return;
        }
        // Create an auxiliary pointer to help the child out of the circle to point to the last node
        boyNode helper = first;
        while(true){
            if(helper.getNext() == first){
                break;
            }
            helper = helper.getNext();
        }

        // Let the first and helper move k-1 times before starting counting
        for(int j=0;j<startNum-1;j++){
            first = first.getNext();
            helper = helper.getNext();
        }
        // When the child counts off, let the first and helper pointers move m-1 times at the same time, and then make a circle
        // Cyclic operation
        while(true){
            if(helper == first){//There is only one node in the circle
                break;
            }
            //Let the first and helper pointers move countNum-1 times at the same time
            for(int j=0;j<countNum-1;j++){
                first = first.getNext();
                helper = helper.getNext();
            }
            // At this time, the first point is the child who is going out of the circle
            System.out.printf("child%d Out of circle\n",first.getNo());
            first = first.getNext();
            helper.setNext(first);

        }

        System.out.printf("The last child left in the circle%d\n",helper.getNo());
    }
}

class boyNode{
    public int no;//number
    private boyNode next;

    public boyNode(int no)
    {
        this.no = no;
        next = null;
    }

    public int getNo() {
        return no;
    }

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

    public boyNode getNext() {
        return next;
    }

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

Stack

Actual scenario: the computer needs to read the string form of a line of arithmetic expression, distinguish between numbers and operators, and then calculate.

eg: String str = "7*222-22-1+1/1"

introduce

  • Out of stack: pop

  • Stack: push

Array simulation stack

package Stack;

import java.util.Scanner;

public class _Implementation of stack_ {
    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack(4);
        String key = "";
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);

        while(loop){
            System.out.println("--------------------------");
            System.out.println("show:Display stack");
            System.out.println("exit:Exit program");
            System.out.println("push:Add data to stack");
            System.out.println("pop:Fetch data from the top of the stack");
            System.out.println("Enter your choice");

            key = scanner.next();
            switch (key){
                case "show":
                    stack.list();
                    break;
                case "exit":
                    scanner.close();
                    System.out.println("Exited");
                    System.exit(0);
                case "pop":
                    try {
                        int value = stack.pop();
                        System.out.printf("The data out of the stack is:%d\n",value);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case "push":
                    System.out.println("Enter the data you want:");
                    int value = scanner.nextInt();
                    stack.push(value);
                    break;
                default:
                    break;

            }
        }
    }
}




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

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

    //Judge whether it is full
    public Boolean isFull(){
        return top==maxSize-1;
    }

    //Judge whether it is empty
    public Boolean isEmpty(){
        return top == -1;
    }

    // Stack push
    public void push(int value){
        if(isFull()){
            System.out.println("Don't continue adding when the stack is full");
            return;
        }
        top++;
        stack[top] = value;
    }

    // Out of stack - pop
    public int pop(){
        if(isEmpty()){
            throw new RuntimeException("The stack is empty");
        }
        top--;
        return stack[top+1];
    }

    //Traverse the top of the stack
    public void list(){
        if(isEmpty()){
            throw new RuntimeException("The stack is empty,no data");
        }
        for (int i = top; i >=0 ; i--) {
            System.out.printf("stack[%d]:%d\n",top,stack[top]);
        }
    }

}

Linked list simulation stack

package Stack;

public class _Linked list implementation of stack_ {
    public static void main(String[] args) {
        linkedListStack stack = new linkedListStack();
        stack.push(new Node(10));
        stack.push(new Node(3));
        stack.push(new Node(5));
        stack.list();
        System.out.println("-------------------");
        System.out.println(stack.pop());
    }
}

class linkedListStack{
    Node head = new Node(-1);

    // When a push is added, it is added directly behind the head
    public void push(Node newNode){
        if(head.next == null){
            head.next = newNode;
        }else{
            newNode.next = head.next;
            head.next = newNode;
        }

    }

    // Pop pop up stack top element
    public int pop(){
        if(head.next == null) {
            throw new RuntimeException("Stack empty");
        }
        int value = head.next.data;
        head.next = head.next.next;
        return value;
    }

    // ergodic
    public void list(){
        Node temp = head.next;
        int cnt = 1;
        while(temp!=null){
            System.out.printf("The first%d The first element is%d\n",cnt++,temp.data);
            temp = temp.next;

        }
    }
}

class Node{
    public int data;
    public Node next;

    public Node(int data){
        this.data = data;
        next = null;
    }
}

Implementation of solution calculator

Idea:

code:

package Stack;

import java.util.concurrent.BlockingDeque;

/*
Problems: during the addition process, it will be regarded as a calculation error. For example, when the operator after the 3-3 * 2 + 6 minus sign has higher priority, another small sign will be changed

Solution: when adding the symbol stack, we judge whether (the previous one is minus sign) the sign change minus change plus change minus change

Limitation: calculation with parentheses has not been processed
 */

public class _Stack implementation calculator_ {
    public static void main(String[] args) {
        String expression = "3-3*2+6";  //There is also a problem here. The problem is that only the statistical operator will make an error. It has been solved
//        String expression = "700+20*6-4";
        ArrayStack2 numberStack = new ArrayStack2(10);
        ArrayStack2 operStack = new ArrayStack2(10);

        int index = 0;//index is used to scan
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        String keepNum = "";//Number of spliced multiple bits
        char ch = ' ';//The char scanned each time is saved to ch
        while(true){
            //Get every character of expression at once
            ch = expression.substring(index,index+1).charAt(0);
            //Judge what ch is and deal with it accordingly
            if(operStack.isOper(ch)){//If it is an operator judgment
                if(operStack.isEmpty()){//If the symbol stack is empty, put it directly into the stack
                    operStack.push(ch);
                }else{
                    if(operStack.priority(ch)<= operStack.priority(operStack.peek())){//If the operator priority is smaller or equal than before, it shall be calculated once
                        if(operStack.isMinus() == '-'){
                            num1 = numberStack.pop();
                            num2 = numberStack.pop();
                            oper = operStack.pop();
                            res = operStack.cal(num1,num2,oper);
                            numberStack.push(res);//Put the results into the stack
                            if(ch=='-'){
                                ch = '+';
                                operStack.push(ch);
                            }else if(ch=='+'){
                                ch = '-';
                                operStack.push(ch);
                            }
                        }else{
                            num1 = numberStack.pop();
                            num2 = numberStack.pop();
                            oper = operStack.pop();
                            res = operStack.cal(num1,num2,oper);
                            numberStack.push(res);//Put the results into the stack
                            operStack.push(ch);//The current operator is still put on the symbol stack
                        }
                    }else{
                        operStack.push(ch);
                    }
                }

            }else{//The number directly enters the number stack. If the next digit is still a number, not the last digit, and the next digit of the next digit is not a number, the number of digits will not be added
                keepNum += ch;
                if(index == expression.length()-1){//If it is the last bit, put it directly into the stack
                    numberStack.push(Integer.parseInt(keepNum));
                }else{
                    if(numberStack.isOper(expression.substring(index+1,index+2).charAt(0))){//If the next digit is not a number, it is a number and continues to be spliced
                        numberStack.push(Integer.parseInt(keepNum));
                        keepNum = "";//Need to empty
                    }
                }

            }
            index++;
            if(index>=expression.length()){
                break;
            }
        }

        //Then the calculation knows that there is no operator
        while(true){
            if(operStack.isEmpty()){
                break;
            }else{
                num1 = numberStack.pop();
                num2 = numberStack.pop();
                oper = operStack.pop();
                res = numberStack.cal(num1,num2,oper);
                numberStack.push(res);
            }

        }

        int res2 = numberStack.pop();
        System.out.println(res2);

    }
}


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

    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    //Judge whether it is full
    public Boolean isFull() {
        return top == maxSize - 1;
    }

    //Judge whether it is empty
    public Boolean isEmpty() {
        return top == -1;
    }

    // Stack push
    public void push(int value) {
        if (isFull()) {
            System.out.println("Don't continue adding when the stack is full");
            return;
        }
        top++;
        stack[top] = value;
    }

    // Out of stack - pop
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("The stack is empty");
        }
        top--;
        return stack[top + 1];
    }

    //Traverse the top of the stack
    public void list() {
        if (isEmpty()) {
            throw new RuntimeException("The stack is empty,no data");
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("stack[%d]:%d\n", top, stack[top]);
        }
    }

    // Returns the priority of a number
    public int priority(int oper){
        // Suppose there are only these four operators
        if(oper == '*'||oper == '/'){
            return 1;
        }else if(oper == '+'||oper == '-'){
            return 0;
        }else{
            return -1;
        }

    }

    // Determine whether it is an operator
    public Boolean isOper(char val){
        return val=='*'||val =='/'||val == '+'|| val=='-';
    }

    // Judgment minus sign
    public int isMinus(){
        return stack[top-1];
    }

    // computing method

    /**
     *
     * @param num1  Number of pop first
     * @param num2  Number of post pop
     * @param oper  Operator
     * @return
     */
    public int cal(int num1,int num2,int oper){
        int res = 0;
        switch(oper){
            case '+':
                res = num1+num2;
                break;
            case '-':
                res = num2-num1;
                break;
            case '*':
                res = num1*num2;
                break;
            case '/':
                res = num2/num1;
            default:
                break;
        }
        return res;
    }

    //You can return the top of the stack element, but it won't really pop up
    public int peek(){
        return stack[top];
    }


}


Pre middle suffix expression

Prefix expression: (Polish expression)

Infix expression: (human computing method)

Suffix expression: (inverse Polish expression)

Posted by calmchess on Sun, 26 Sep 2021 01:13:20 -0700