# 1 - queue, linked list, stack

## 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
• 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.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.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;
}

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]);
}
}

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;
}

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;
}

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.1 refer to big talk data structure

#### 5.2.1 code example of single linked list directly inserted into tail node

```package LinkedList;

public static void main(String[] args) {
Node n1 = new Node(1,1);
Node n2 = new Node(2,2);
Node n3 = new Node(3,3);
s1.list();
// out message
// Node{num=1, data=1}
// Node{num=2, data=2}
// Node{num=3, data=3}
}
}

// The head node cannot be moved
private Node head = new Node(0, 0);

// temp gets the temporary node and starts traversal

// 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;
}
temp.next = n;
}

public void list(){
// first to assert isEmpty
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
// 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.
```
// Sort from small to large according to node num
// 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
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){
flag = true;
break;
}
}

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){
return;
}
// Find the node to modify
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
}
}
```
• 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
return;
}

boolean flag = false;
while (true){
if (temp.next.num == num){
// eureka
flag = true;
break;
}
if (temp.next == null){
break;
}
temp = temp.next;   // No, move back
}
if (flag){
temp.next = temp.next.next;
System.out.println("Delete complete");
}
else {
}
}
```

• 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.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(){
}

// Judge stack empty
public boolean isEmpty(){
}

// 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

Tags: data structure

Posted on Mon, 01 Nov 2021 01:52:56 -0400 by snoopy13