# Data structure and linear table

Posted by Matth_S on Mon, 10 Jan 2022 12:33:48 +0100

## Chapter I overview

### Section I overview of data structure

Data structure is a programming discipline that studies non numerical calculation. Nicklaus Wirth, the father of Pascal who won the Turing Award, put forward a famous formula:

Algorithm + data structure = Program

Data structure is a way for computers to store and organize data. A data structure is a collection of data elements that have one or more specific relationships with each other. In general, carefully selected data structures can bring higher operation or storage efficiency. Data structure is often related to efficient retrieval algorithm and index technology.

#### 1. Basic concepts

##### (1) Data

Data is the general name of the objects processed by computer programs. For example, when calculating differential equations, the processing object is some data, and in image processing, the object is encoded image information, etc.

##### (2) Data Element

The basic unit of data, which can be divided into several data items, and the data item is the smallest unit of data. For example, in a student performance management system, the performance of each student can be regarded as a data element, and the performance of each subject can be regarded as different data items.

##### (3) Data Object

It is a collection of data elements with the same properties and a subset of data. For example, the data object of real number is real number set R.

##### (4) Data Structure

Is a collection of data elements that have one or more specific relationships with each other.

#### 2. Logical structure and physical structure

##### (1) Logical structure

Logical structure refers to the logical relationship between data elements in data objects, which is divided into the following four structures:

• Set structure: the data elements in the set structure have no relationship except that they belong to the same set
• Linear structure: the relationship between data elements in a linear structure is a one-to-one linear relationship
• Tree structure: the elements in the tree structure have a one to many hierarchical relationship
• Graphic structure: the elements in the graphic structure have any many to many relationship
##### (2) Physical structure

Physical structure refers to the storage form of data logical structure in the computer, which generally has the following two forms:

1. Sequential storage structure: sequential storage structure is to store data elements in storage units with continuous addresses, and the logical relationship of data is consistent with the physical relationship. As shown below:

2. Chain storage structure: chain storage structure stores data elements in any data unit. This group of storage units can be continuous or discontinuous. As shown below:

### Section II algorithm overview

The algorithm is a description of the steps to solve a specific problem, which is expressed as a finite sequence of instructions in the calculation set, and each instruction represents one or more operations.

#### 1. Characteristics of the algorithm

The algorithm has five basic characteristics: input, output, finiteness, certainty and feasibility

• Input: the algorithm should have zero or more inputs
• Output: the algorithm has at least one or more outputs
• Finiteness: finiteness means that the algorithm ends automatically after executing limited steps without infinite loops, and each step can be completed in an acceptable time.
• Certainty: every step of the algorithm has definite significance
• Feasibility: every step of the algorithm must be feasible, and each step can be completed by executing a limited number of times

#### 2. Requirements for algorithm design

The algorithm design has the following requirements:

1. Correctness: the correctness of the algorithm means that the algorithm should at least have no ambiguity in input, output and processing, can correctly respond to the needs of the problem, and can get the correct answer to the problem
2. Readability: another purpose of algorithm design is to facilitate reading, understanding and communication
3. Robustness: when the input data is illegal, the algorithm can also make relevant processing, rather than producing abnormal or inexplicable results
4. High time efficiency and low storage: the design algorithm should try to meet the requirements of high time efficiency and low storage

#### 3. Measurement method of algorithm efficiency

##### (1) Post statistical method

This method mainly compares the running time of programs compiled by different algorithms by using computer timers through designed test programs and data, so as to determine the efficiency of the algorithm

Defects:

• It must be realized that the program is well prepared
• The comparison of time depends on environmental factors such as computer hardware and software
• The test data design of the algorithm is difficult, and the running time of the algorithm is often closely related to the scale of the test data
##### (2) Ex ante analysis and estimation method

Prior analysis and estimation method before computer programming, a statistical method is used to estimate the algorithm

Depends on the following factors:

1. The algorithm adopts strategies and methods
2. Code quality generated by compilation
3. Problem input scale
4. The speed at which the machine executes commands

#### 4. Algorithm time complexity

When analyzing the algorithm, the total execution times T(n) of the statement is a function of the problem scale n, and then analyze the change of T(n) with n to determine the order of magnitude of T(n). The time complexity of the algorithm, that is, the time measurement of the algorithm, is recorded as: T(n) = O(f(n))

Common time complexity:

O ( 1 ) < O ( l o g n ) < O ( n l o g n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) {O(1) < O(log n) < O(nlog n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)} O(1)<O(logn)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

## Chapter 2 linear table (List)

Linear table (List): a linear table represents a finite sequence of zero or more data elements

### Section 1 sequential storage of linear tables (ArrayList)

#### 1. General

Definition of sequential storage: the sequential storage structure of linear table refers to storing the data elements of linear table at one time with a section of storage unit with continuous addresses, which is equivalent to one-dimensional array

Linear tables stored in sequential storage are also called ArrayList

Properties of sequence table:

• data []: an array that implements the sequence table
• size: the number of data stored in the sequence table

Method of sequence table:

·

#### 2. Implement List and ArrayList through Java code

##### (1) Create List interface
```package p1.interfaces;

import java.util.Comparator;

public interface List<E> extends Iterable<E> {
public void remove(E element);//Deletes the specified element
public E remove(int index);//Deletes the element at the specified subscript
public E get(int index);//Gets the element at the specified subscript
public E set(int index,E element);//Modify the element at the specified subscript
public int size();//Get the number of elements
public int indexOf(E element);//View the subscript position of the first occurrence of the element (from left to right)
public boolean contains(E element);//See if the linear table contains elements
public boolean isEmpty();//Judge whether the linear table is empty
public void clear();//Empty linear table
public void sort(Comparator<E> c);//The linear table is sorted according to the contents of the comparator
public List<E> subList(int fromIndex, int toIndex);//In the original linear table, the sub list is intercepted by [fromIndex,toIndex) interval
}
```
##### (2) Create an ArrayList class to implement the List interface
```package p2.array.lists;

import p1.interfaces.List;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Objects;

public class ArrayList<E> implements List<E> {
private E[] data;
private int size = 0;
//Default capacity
private static int DEFAULT_CAPACITY = 10;

//The default constructor creates a linear table of default capacity
public ArrayList(){
data = (E[]) new Object[DEFAULT_CAPACITY];
size = 0;
}
//Creates a linear table of the specified size
public ArrayList(int capacity) {
if (capacity < 0){
throw new IllegalArgumentException("capacity are not be null");
}
DEFAULT_CAPACITY = capacity;
data = (E[]) new Object[DEFAULT_CAPACITY];
size = 0;
}
//Convert an array to a linear table
public ArrayList(E[] array) {
if (array == null || array.length == 0){
throw new IllegalArgumentException("capacity are not be null");
}
data = (E[]) new Object[DEFAULT_CAPACITY];
for (int i = 0; i < array.length ; i++) {
}
}

@Override
}

@Override
public void add(int index, E element) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("add index out of range");
}
if (size == data.length) {
resize(2 * data.length);
}
for (int i = size -1; i >= index ; i--) {
data[i + 1] = data[i];
}
data[index] = element;
size ++;
}
//Expansion or contraction, not provided to the outside world
private void resize(int newlen) {
E[] newData = (E[]) new Object[newlen];
for (int i = 0; i < size; i++) {//No subscript out of bounds
newData[i] = data[i];
}
data = newData;
}

@Override
public void remove(E element) {
int index = indexOf(element);
if (index == -1) {
throw new IllegalArgumentException("The element to be deleted does not exist");
}
remove(index);
}

@Override
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("remove index out of range");
}

E ret = data[index];
for (int i = index + 1; i < size  ; i++) {
data[i - 1] = data[i];
}
data[size-1] = null;
size --;
//When the effective element is one fourth of the capacity and the capacity is less than or equal to the default capacity, shrink the capacity
if (size == data.length/4 && data.length > DEFAULT_CAPACITY) {
resize(data.length/2);
}
return ret;
}

@Override
public E get(int index) {
if (index < 0 ||index >= size){
throw new IllegalArgumentException("get index out of range");
}
return data[index];
}

@Override
public E set(int index, E element) {
if (index < 0 ||index >= size){
throw new IllegalArgumentException("set index out of range");
}
E ret = element;
//data[index] = element;
return ret;
}

@Override
public int size() {
return size;
}

private int capacity(){
return data.length;
}

@Override
public int indexOf(E element) {
/*
* == Reference data type comparison address
* == Basic data type comparison value
* */
for (int i = 0; i < size; i++) {
if (data[i] == element) {
return i;
}
}
return -1;
}

@Override
public boolean contains(E element) {
int count = indexOf(element);
boolean flag = false;
if (count != -1) {
flag = true;
}
return flag;
}

@Override
public boolean isEmpty() {
return size == 0;
}

@Override
public void clear() {
data = (E[]) new Object[DEFAULT_CAPACITY];
size = 0;
}
@Override
public void sort(Comparator<E> c){

if (c == null) {
throw new IllegalArgumentException("comparator can not be null");
}
for (int i = 1; i < size; i++) {
E e = data[i];
int j = 0;
for (j = i; j > 0 && c.compare(data[j - 1], e) > 0; j--) {
data[j] = data[j - 1];
}
data[j] = e;
}
}

@Override
public List<E> subList(int fromIndex, int toIndex) {
if (fromIndex < 0 ||toIndex >= size || fromIndex > toIndex){
throw new IllegalArgumentException("index out of range");
}
ArrayList<E> list = new ArrayList<>();
for (int i = fromIndex; i < toIndex; i++) {
}

return list;
}

@Override
public boolean equals(Object o) {
//1. Empty judgment first
if (o == null) {
return false;
}
if (this == null) {
return false;
}
if (o instanceof ArrayList) {
ArrayList<E> other = (ArrayList<E>) o;
if (this.size != other.size) {
return false;
}
for (int i = 0; i < size; i++) {
if (!(data[i].equals(other.data[i]))) {
return false;
}
}
return true;
}
return false;
}

@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append('[');
if(isEmpty()){
stringBuilder.append(']');
}else{
for (int i = 0; i < size; i++) {
stringBuilder.append(data[i]);
if (i == size-1){
stringBuilder.append(']');
}else{
stringBuilder.append(',');
stringBuilder.append(' ');
}
}
}
return stringBuilder.toString();
}

@Override
public Iterator<E> iterator() {
return new ArrayListIterator();
}
class ArrayListIterator implements Iterator<E>{
private int cur = 0;
@Override
public boolean hasNext() {
return cur < size;
}

@Override
public E next() {
return data[cur++];
}
}
}
```

### Section 2 stack

#### 1. Definition of stack

Stack is a special linear table. It is limited to insert and delete operations only in one section of the linear table. One end that allows insertion and deletion is called the top of the stack and the other end is called the bottom of the stack. Because only one end is inserted or deleted, the later inserted elements will be deleted before the first inserted elements, so the stack is also called "last in first out" linear table

Stack entry (stack entry, stack pressing): the process of adding elements to the stack

Out of stack (pop stack): delete the elements in the stack

#### 2. Realize Stack and ArrayStack through code

##### (1) Define Stack interface
```package p1.interfaces;

public interface Stack<E> extends Iterable<E> {
public int size();//Returns the number of elements currently stored in the stack
public boolean isEmpty();//Determine whether the stack is empty
public void push(E element);//Stacking (pressing) operation
public E pop();//Out of stack (pop stack) operation
public E peek();//Get stack top element
public void clear();//Empty stack
}
```
##### (2) Implement the Stack interface through the ArrayStack class
```package p2.array.lists;

import p1.interfaces.Stack;

import java.util.Iterator;

public class ArrayStack<E> implements Stack<E> {
ArrayList<E> list ;
public ArrayStack(){
list = new ArrayList<>();
}
public ArrayStack(int capacity){
list = new ArrayList<>(capacity);
}
public ArrayStack(E[] arr){
list = new ArrayList<>(arr);
}

@Override
public int size() {
return list.size();
}

@Override
public boolean isEmpty() {
return list.isEmpty();
}

@Override
public E pop() {
return list.remove(list.size()-1);
}

@Override
public E peek() {
return list.get(list.size() - 1);
}

@Override
public void clear() {
list.clear();
}

@Override
public void push(E element) {
}

@Override
public String toString() {
return list.toString();
}

@Override
public Iterator iterator() {
return list.iterator();
}
}

```

#### 3. Stack application: infix expression operation

##### (1) Definition of infix expression
• It is a general expression method of arithmetic or logic formula. The operator is in the middle of the operand in the form of infix (example: 3 + 4)
• Compared with prefix expression (e.g. + 34) or suffix expression (e.g. 34 +), infix expression is not easy to be parsed by computer, but it is still used by many programming languages because it conforms to people's common usage.
• Unlike prefix or suffix notation, infix notation brackets are required.
##### (2) Overview of infix expression operation implementation process

with ( 10 + 20 / 2 ∗ 3 ) / 2 + 8 {(10+20/2*3)/2+8} (10 + 20 / 2 * 3) / 2 + 8 as an example

First, you can add an appropriate delimiter to the infix expression to split the expression and initialize the string

```public static String initString(String expression){
//Add spaces at both ends of all non numeric characters
//Traverse the string from left to right and use stringbuilder to splice
StringBuilder stringBuilder = new StringBuilder();
char c;
for (int i = 0; i < expression.length(); i++) {
c = expression.charAt(i);
if (c=='('||c==')'||c=='+'||c=='-'||c=='*'||c=='/'){
stringBuilder.append(',');
stringBuilder.append(c);
stringBuilder.append(',');
}else{
stringBuilder.append(c);
}
}
return stringBuilder.toString();
}
```

Secondly, divide the string, define two stacks, one for storing operators and the other for storing numbers, and then operate on these stacks.

```private static int eValuete(String expression) {
ArrayStack<Character> operator = new ArrayStack<>();
ArrayStack<Integer> integers = new ArrayStack<>();
//1. Initialize the expression and add spaces on both sides of each symbol
expression = initString(expression);
//2. Cut the string xz
String[] tokens = expression.split(",");
for (String token:tokens) {
//Filter empty strings
if (token.length() == 0){
continue;
}else if (token.equals("+") || token.equals("-")){//When traversing to the plus and minus sign, look at the top of the stack. There are no elements at the top of the stack. Go directly in
while(!operator.isEmpty() && (operator.peek() == '+' || operator.peek() == '-' || operator.peek() == '*' || operator.peek() == '/')){
//If the previous operator is + - * / or other operators, pop stack calculation
processAnOperator(integers,operator);
}
operator.push(token.charAt(0));
}else if (token.equals("*") || token.equals("/")){
while(!operator.isEmpty() && (operator.peek() == '*' || operator.peek() == '/')){
//If the previous operator is + - * / or other operators, pop stack calculation
processAnOperator(integers,operator);
}
operator.push(token.charAt(0));
}else if(token.equals("(")){
operator.push(token.charAt(0));
}else if(token.equals(")")){
while(operator.peek() != '('){
//If the previous operator is + - * / or other operators, pop stack calculation
processAnOperator(integers,operator);
}
operator.pop();
}else{
integers.push(Integer.parseInt(token));
}

}
//Process the last operator
while(!operator.isEmpty()){
processAnOperator(integers,operator);
}
return integers.pop();
}
//The operator stack bounces one element, the number stack bounces two elements and operates, and then the result is put on the stack
private static void processAnOperator(ArrayStack<Integer> integers, ArrayStack<Character> operator) {
char op = operator.pop();
int num1 = integers.pop();
int num2 = integers.pop();
if (op == '+') {
integers.push(num2 + num1);
} else if (op == '-') {
integers.push(num2 - num1);
} else if (op == '*') {
integers.push(num2 * num1);
} else {
integers.push(num2 / num1);
}
}
```

Finally, we are testing these functions with a main()

``` public static void main(String[] args) {
String expression = "(10+20/2*3)/2+8";
try {
int result = eValuete(expression);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Wrong expression :" + expression);
}

}
```

Topics: Java Algorithm data structure