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)