1. Logical structure and physical structure (storage structure)
1.1 logical structure
- Set structure (unrelated)
- Linear structure (one to one)
- Representative: linear table, stack, queue, string
- Nonlinear structure
- Tree structure (one to many)
- Graphic structure (many to many)
1.2 physical structure
- Sequential storage structure
- Linked Storage Structure
- Indexes
- Hash table
2. Sparse array
2.1 introduction
- When there are few valid values and many zeros in an array, it can be stored in a sparse array. SparseArray
- As shown below, row 0 of the sparse array, the first column 6 indicates how many rows the original array has, the second column 7 indicates how many columns the original array has, and the third column 8 indicates how many non-0 elements the original array has. The row and column of the non-0 element of the records from row 1 to the last row of the sparse array and its value.
- Thus, the column of the sparse array must be 3, and the number of rows is the number of non-0 elements of the original array + 1 (row 0).
2.2 code implementation
package SparseArray; public class Demo01 { public static void main(String[] args) { // 1. Create the original array. As long as the required place is assigned a value other than 0, the rest will be 0 by default int[][] o_array = new int[5][6]; o_array[1][3] = 1; o_array[2][4] = 2; o_array[0][3] = 5; o_array[3][2] = 4; // 2. Get the rows and columns of the original array int lenx = o_array.length; int leny = o_array[0].length; // 3. Get the number of non-0 elements int non_zero = 0; for (int i =0; i<lenx;i++){ for (int j=0;j<leny;j++){ int temp = o_array[i][j]; if(temp!=0){ non_zero++; } } } // 4. Create a sparse array int[][] sparse_array = new int[non_zero+1][3]; sparse_array[0][0] = lenx; sparse_array[0][1] = leny; sparse_array[0][2] = non_zero; // 5. Traverse the original array and fill the non-0 elements into the sparse array int x = 1; for (int i =0; i<lenx;i++){ for (int j=0;j<leny;j++){ int temp = o_array[i][j]; if(temp!=0){ sparse_array[x][0] = i; sparse_array[x][1] = j; sparse_array[x][2] = temp; x++; } } } // 6. Output original array System.out.println("The original array is as follows"); for (int[] row: o_array){ for (int data:row){ System.out.printf("%d\t", data); } System.out.println(); } // 7. Output sparse array System.out.println("The sparse array is as follows"); for (int[] row:sparse_array){ for (int data:row){ System.out.printf("%d\t", data); } System.out.println(); } // 8. Restore the sparse array to the original array // 8.1 first obtain the data in the first row of the sparse array to create the original array size int lenx2 = sparse_array[0][0]; int leny2 = sparse_array[0][1]; int[][] array2 = new int[lenx2][leny2]; // 8.2 traverse the sparse array, starting from line 2. Restore data for (int i=1; i< sparse_array.length; i++){ array2[ sparse_array[i][0] ][ sparse_array[i][1] ] = sparse_array[i][2]; } // 8.3 output new restored original array System.out.println("The restored original array is as follows"); for (int[] row: array2){ for (int data:row){ System.out.printf("%d\t", data); } System.out.println(); } } }
3 queue
3.1 introduction
- Queue is an ordered list, which can be implemented by array or linked list
- First in first out
3.2 code implementation
-
The default value of rear and front is - 1 (when adding and fetching data, first + 1 and then add). If the default value is 0, the operation process is different (when adding, first add, then rear+1, when fetching data, first fetch and then front+1).
-
The following queue is one-time. After the queue is filled with values, it can no longer be added, because the filled values do not leave the queue, but only return values.
public class Demo { public static void main(String[] args) { ArrayQueue a = new ArrayQueue(5); a.addQueue(1); a.addQueue(2); a.addQueue(3); a.addQueue(4); a.addQueue(5); a.showAllQueue(); System.out.println(); System.out.println(a.getQueue()); System.out.println(a.getQueue()); System.out.println(a.getQueue()); System.out.println(); a.showAllQueue(); System.out.println(); a.showQueue(); a.addQueue(6); a.addQueue(7); a.addQueue(8); a.showAllQueue(); } } class ArrayQueue{ private int maxSize; // Maximum queue capacity private int front; // Queue header pointer private int rear; // End of queue pointer private int[] arr; // Array, used to simulate the queue and save data // constructor public ArrayQueue(int maxSize){ this.maxSize = maxSize; arr = new int[maxSize]; front = -1; rear = -1; } // Judge whether the queue is full. If the tail pointer = = maximum value - 1 (starting with tail pointer 0), it indicates that it is full public boolean isFull(){ return rear==maxSize-1; } // Judge whether the queue is empty. If the head and tail pointers are the same, it is empty public boolean isEmpty(){ return front==rear; } // Add data to queue public void addQueue(int n){ if (isFull()) { System.out.println("The queue is full and data cannot be added!"); return; } // arr[++rear] = n; // perhaps rear ++; arr[rear] = n; } // Get queue data, that is, take out data from the header public int getQueue(){ if(isEmpty()){ // You cannot return because the value of return may be the value of a queue element throw new RuntimeException("The queue is empty and data cannot be retrieved"); } front++; return arr[front]; } // Print the contents not taken out of the queue public void showQueue(){ if (isEmpty()){ System.out.println("The queue is empty and there is no data"); return; } for (int i=front+1; i<arr.length; i++){ System.out.printf("arr[%d] == %d\t", i, arr[i]); } } // Print all the contents of the queue. Even if there is extracted data, it is only returned, but it is not deleted in arr! public void showAllQueue(){ if (isEmpty()){ System.out.println("The queue is empty and there is no data"); return; } for (int i=0; i<arr.length; i++){ System.out.printf("arr[%d] == %d\t", i, arr[i]); } } // Get header data public int getHead(){ if (isEmpty()) throw new RuntimeException("The queue is empty, unable to get header data"); return arr[++front]; } }
4 ring queue
4.1 introduction
- Because the queue in 3 is one-time, a ring queue is constructed so that the queue can be reused!
- Refer to p114-p117 (very important) of Dahua data structure for details of ring queue
- The reason why rear points to an empty space is to distinguish whether rear == front is empty or full! When rear == front, it is empty, and (the index of the empty space pointed to by rear + 1)% maxSize, if = = front, it is full
4.2 code implementation
package MyQueue; public class CircleQueue { private int maxSize; // Maximum queue capacity private int front; // Queue header pointer, default 0 private int rear; // Points to the next position of the last element of the queue, and the position can only be empty. The default is 0 private int[] arr; // Array, used to simulate the queue and save data // constructor public CircleQueue(int maxSize1){ this.maxSize = maxSize1+1; arr = new int[maxSize]; front = 0; rear = 0; } // Judge whether the queue is full. If the tail pointer = = maximum value - 1 (starting with tail pointer 0), it indicates that it is full public boolean isFull(){ return (rear+1)%maxSize == front; } // Judge whether the queue is empty. If the head and tail pointers are the same, it is empty public boolean isEmpty(){ return front==rear; } // Add data to queue public void addQueue(int n){ if (isFull()) { System.out.println("The queue is full and data cannot be added!"); return; } arr[rear] = n; rear = (rear+1)%maxSize; } // Get queue data, that is, take out data from the header public int getQueue(){ if(isEmpty()){ // You cannot return because the value of return may be the value of a queue element throw new RuntimeException("The queue is empty and data cannot be retrieved"); } int res = arr[front]; front = (front+1)%maxSize; return res; } // Print all the contents of the queue. Even if there is extracted data, it is only returned, but it is not deleted in arr! public void showAllQueue(){ if (isEmpty()){ System.out.println("The queue is empty and there is no data"); return; } for (int i=front; i<front+getSize(); i++){ System.out.printf("arr[%d] == %d\t", i%maxSize, arr[i%maxSize]); } } // Get queue length public int getSize(){ return (rear - front + maxSize)%maxSize; } // Get header data public int getHead(){ if (isEmpty()) throw new RuntimeException("The queue is empty, unable to get header data"); return arr[front]; // front directly points to the first element. After returning, it does not need + +, and the queue needs + +; } }
5 linked list
5.1 refer to big talk data structure
5.2 single linked list
5.2.1 code example of single linked list directly inserted into tail node
package LinkedList; public class SingleLinkedListDemo { public static void main(String[] args) { Node n1 = new Node(1,1); Node n2 = new Node(2,2); Node n3 = new Node(3,3); SingleLinkedList s1 = new SingleLinkedList(); s1.addNode(n1); s1.addNode(n2); s1.addNode(n3); s1.list(); // out message // Node{num=1, data=1} // Node{num=2, data=2} // Node{num=3, data=3} } } class SingleLinkedList { // The head node cannot be moved private Node head = new Node(0, 0); // Add a new node public void addNode(Node n){ // temp gets the temporary node and starts traversal Node temp = head; // Find the last node and add the new node directly while (true){ // If the current node next=null, it means that it is currently the tail node, and the loop will jump out if (temp.next == null){ break; } // Otherwise, look at the next node temp = temp.next; } // Add node temp.next = n; } // Display linked list public void list(){ // first to assert isEmpty if (head.next == null){ System.out.println("the list is empty!"); return; } // head node we can not use, so make temp = head node. // because if head node is used, it will point other value Node temp = head.next; // Judge whether the last node is empty. If it is empty, it means that the current node is the last node, and the cycle is directly pushed out. // If it is not empty, the node information is output and the next node is judged. while (true){ if (temp == null){ break; } System.out.println(temp); temp = temp.next; } } } class Node{ public int num; // Default 0 public int data; // Default 0 public Node next; // Default null public Node(int num, int data){ this.num = num; this.data = data; } // There is no + next, otherwise it will be a doll @Override public String toString() { return "Node{" + "num=" + num + ", data=" + data + '}'; } }
5.2.2 code implementation of single linked list with sorting
- Sort and insert nodes according to num, from small to large
- First find the insertion location, temp node, which must be the previous node of the insertion location.
- Just add an addbynum method.
// Sort from small to large according to node num public void addNodeSortByNum(Node n){ // The head node cannot be modified, so temp == head is used // The head node should be in the previous position of the inserted node, otherwise it cannot be inserted // The previous node cannot be found because there is no precursor pointer Node temp = head; boolean flag = false; // If the added number num exists, it becomes true // Find the location node temp we need to insert. This node is the previous node of the newly inserted node while (true){ if (temp.next == null){ // If temp.next == null, it means that this temp is the tail node and the node we are looking for break; } if (temp.next.num > n.num){ // If the node num after temp > insert node num, it means that it should be inserted in // Between temp node and temp.next node // At this time, temp is the node we are looking for break; } else if (temp.next.num==n.num){ // The added number already exists flag = true; break; } temp = temp.next; // If not found, judge the next node } if (flag){ System.out.println("The inserted number already exists, The number is: "+ n.num); } else{ // Insert into the linked list, after temo n.next = temp.next; temp.next = n; } }
5.2.3 modify nodes and delete nodes
public void updateNodeByNum(Node n){ if (head.next==null){ System.out.println("The linked list is empty!"); return; } // Find the node to modify Node temp = head.next; boolean flag = false; // true means found while (true){ if (temp == null){ break; // The traversal is over. If you can't find it, just exit } if (temp.num == n.num){ // eureka flag = true; break; } temp = temp.next; } if (flag){ // Found. Modify the data of the node temp.data = n.data; } else { // Can't find System.out.printf("Node number not found%d The node cannot be modified\n", n.num); } }
- Deleting a node is a single linked list, so if we want to delete the node indicated by the red arrow, we must find its previous node (indicated by green). Otherwise, the previous node of the deleted node cannot be connected to the next node of the deleted node, and a new linked list cannot be formed.
- Once found, temp.next = temp.next.next.
- If the deleted node has no reference, it will be recycled by GC.
public void deleteNodeByNum(int num){ // Determine whether the linked list is empty if (head.next == null){ System.out.println("The linked list is empty"); return; } Node temp = head; boolean flag = false; while (true){ if (temp.next.num == num){ // eureka flag = true; break; } if (temp.next == null){ // Traversal ended, not found break; } temp = temp.next; // No, move back } if (flag){ temp.next = temp.next.next; System.out.println("Delete complete"); } else { System.out.println("The node was not found, deletion failed"); } }
5.2.5 bidirectional linked list
5.2.6 circular linked list
- There is a one-way circular linked list and a two-way circular linked list
- Solving Joseph's problem with one-way circular linked list
- We use the tail pointer instead of the head pointer, because the head pointer finds the head node is O(1) and the tail node is O(n). Therefore, let the rear node point to the prior ity node (i.e. the last node) of the head node. At this time, the header is rear.next, the first node (the node behind the head node) is rear.next.next, and the tail node is its own O1.
- How to judge if the circular linked list is Full, temp. Next= Head is not Full
- Determine whether it is empty or temp.next == null
6 stacks
6.1 application scenarios
6.2 code representation
package MyStack; public class demo { public static void main(String[] args) { MyStack m1 = new MyStack(10); m1.push(1); m1.push(2); m1.push(3); m1.push(4); m1.push(5); m1.push(6); m1.push(7); m1.push(8); m1.push(9); m1.push(10); m1.list(); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); System.out.println(m1.pop()); } } class MyStack{ private int maxSize; // The size of the stack. The index should be - 1, so top < = maxsize-1 private int top = -1; // Top stack top private int[] stack; // Array simulation stack public MyStack(int maxSize){ this.maxSize = maxSize; stack = new int[this.maxSize]; } // Determine whether the stack is full public boolean isFull(){ return top == maxSize-1; } // Judge stack empty public boolean isEmpty(){ return top == -1; } // Push public void push(int value){ if (isFull()){ System.out.println("stack is full"); return; } stack[++top] = value; } // Out of stack public int pop(){ if (isEmpty()){ throw new RuntimeException("stack is empty"); } return stack[top--]; } // Traverse the stack and display data from the top of the stack public void list(){ if (isEmpty()){ System.out.println("stack is empty"); return; } // The following method does not work. Because the top value is modified, you need to replace top with temp // while ( !(top<0) ){ // System.out.println(stack[top--]); // } int temp = top; while ( !(temp<0) ){ System.out.println("stack[" + temp + "] = " + stack[temp]); temp--; } // Video method // for (int i=top; i>=0;i--){ // System.out.printf("stack[%d] = %d\n", i, stack[i]); // } } }
6.3 four operation cases
https://www.bilibili.com/video/BV1E4411H73v?p=33&spm_id_from=pageDriver