Basic understanding of sequence structure
Definition:
A storage structure that stores logically adjacent data elements in physically adjacent storage units (occupies a continuous storage unit and cannot be vacated in the middle)
Storage location calculation:
LOC ( a ( i + 1 ) ) = LOC ( a ( i ) ) + l LOC(a(i+1))=LOC(a(i))+lLOC(a(i+1))=LOC(a(i))+l
L O C ( a ( i ) ) = L O C ( a ( j ) ) + ( i − j ) l LOC(a(i))=LOC(a(j))+(i-j)l LOC(a(i))=LOC(a(j))+(i−j ) l
where lll is the storage unit required for each element
The advantages of the sequence table:
the logical relationship is represented by the adjacent physical position, and any element can be randomly accessed
The sequential storage representation of a sequence table:
[ Contiguous addresses, sequential storage, random access, same type ] ==> array (element)
So we can use a one-dimensional array to represent the sequence table. But the length of the sequence table can be changed; while the length of the array is immutable, so we will use an additional variable to indicate the length of the current position in the sequence table
# define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
typedef struct{
ElemType elem[LIST_INIT_SIZE];
int lenth; //当前长度
}SqList
Note: The difference between the logical bit order and the physical bit order is 1 (because the first item of the array is a[0])
Example: polynomial sequential storage structure type definition
P ( x ) = A xa + B xb + C xc + ⋅ ⋅ ⋅ + Z ( i ) xz P(x)=Ax^a+Bx^b+Cx^c+·· ·+Z(i)x^zP(x)=Axa+Bxb+Cxc+⋅⋅⋅+Z(i)x
The linear table of z
is P = ( ( A , a ) , ( B , b ) , ( C , c ) , . . . , ( Z , z ) ) P = ( ( A , a ) , ( B , b ) , ( C , c ) , . . . , ( Z , z ) )P=((A,a),(B,b),(C,c),...,(Z,z))
# define MAXSIZE 1000
typedef struct{
//多项式非零项的意义
float p; //系数
int e; //指数
}Polynomial;
typedef struct{
Polynomial *elem; //存储空间的基地址
int length; //多项式中当前项的系数
}SqList; //多项式的顺序存储结构类型为SqList
Replenish
Supplement 1: The difference between static and dynamic arrays
Array static allocation | Array dynamic allocation |
---|---|
typedef struct{ | typedef struct{ |
ElemType data[maxsize]; | **ElemType *data; ** |
int length; | int length; |
}SqList; //Sequence list type | }SqList; //Sequence list type |
In the static allocation of the array, data[maxsize] essentially stores the address of data[0]; and the pointer *data also stores the address, which is essentially the same. The dynamic allocation of arrays is done by applying for storage space:
SqList L;
L.data = (ElemType*)malloc(sizeof(ElemType)×Maxsize)
Supplement 2: Common functions
The header file needs to be loaded: <stdlib.h>
malloc(m) function: open up an address space of m bytes length, and return the first address of this space
sizeof(x) operation: calculate the length of variable x
free§ function: release the storage space of the variable pointed to by the pointer p, that is, completely delete a variable
(ElemType*)malloc...: coercion type method
Supplement 3: The exchange problem of a and b
Reference type as parameter (C++):
int i=5;
int &j=i;
j is a reference type, when the value of i changes, the value of j will also change accordingly
For example, the function of exchanging a and b can be done in the following two ways:
| 利用指针类型 | 利用引用类型 |
| ----------------------------- | --------------------------- |
| #include <iostream.h> | #include <iostream.h> |
| void swap(float *m,float *n){
| void swap(float&m,float&n){
|
| float temp; | float temp; |
| temp = *m; | temp=m; |
| *m = *n; | m=n; |
| *n = temp; | n=temp; |
| } | } |
| void main(){
| void main(){
|
| float a,b, *p1, *p2; | float a,b; |
| cin>>a>>b; | cin>>a>>b; |
| p1=&a; p2=&b; | swap(a,b); |
| swap(p1,p2); | count<<a<<endl<<b<<endl; |
| count<<a<<endl<<b<<endl; | } |
| } | |
Supplement 4: Macro definition
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
Supplement 5: Memory related
software | C | C++ |
---|---|---|
get memory | malloc | new |
free memory | free | delete |
Implementation of basic operations
Linear list initialization: InitList(&L)
Operation result: Construct an empty linear list L
C++:
C:
Linear list destruction: DestoryList(&L)
Initial condition: the linear table L already exists
Operation result: destroy the linear table L
C++:
C:
C(1):
Clear the linear list: ClearList(&L)
Initial condition: the linear table L already exists
Operation result: reset the linear table L to an empty table
C++:
C:
Judgment for clearing the linear table: ListEmpty(L)
Initial condition: the linear table L already exists
Operation result: If the linear table L is an empty table, return TRUE; otherwise return FALSE
C++:
C:
Linear table length: ListLength(L)
Initial condition: the linear table L already exists
Operation result: return the number of data elements in the linear table L
C++:
C:
Linear table lookup: GetElem(L,i,&e)
Initial conditions: the linear list L already exists, 1≤i≤ListLength(L)
Operation result: use e to return the value of the i-th data element in the linear table L
C++:
C:
Linear table positioning: LocateElem(L,e,compare())
**Initial conditions: **Linear table L already exists, compare() is the decision function of data elements
**Operation result:** Returns the bit sequence of the first data element in L that satisfies compare() with e. If such an element does not exist, the return value is 0
C++:
C:
Analysis of Algorithms:
The expected frequency (average lookup length is) is
( 1 + 2 + 3 + 4 + 5 + 6 + ⋅ ⋅ ⋅ + n − 1 + n ) / n = ( n + 1 ) / 2 (1+2+3+ 4+5+6+···+n-1+n)/n=(n+1)/2(1+2+3+4+5+6+⋅⋅⋅+n−1+n)/n=(n+1 ) /2
to expand on:
The situation in the above figure is the result when the search probabilities are equal.
Linear table element insertion: ListInsert(&L,i,e)
Initial conditions: the linear list L already exists, 1≤i≤ListLength(L)+1
Operation result: insert a new data element e at the i-th position of L, and increase the length of L by one
Algorithm thinking:
1) Determine whether the insertion position i is legal.
2) Determine whether the storage space of the sequence table is full, and return ERROR if it is full
C:
Algorithm analysis:
The insertion position has the following three situations:
① If it is inserted at the end, there is no need to move at all, and the speed is faster
② If it is inserted in the middle of the position, a certain number of elements need to be moved at a moderate speed
③ If it is inserted at the front, all elements in the table need to be moved backwards, and the speed is very slow
So what about the average?
We know that there are a total of n+1 insertion positions, and the i-th insertion position needs to be moved n-i+1 times, then
( 1 + 2 + 3 + 4 + 5 + 6 + ⋅ ⋅ ⋅ + n − 1 + n ) / ( n + 1 ) = n / 2 (1+2+3+4+5+6+···+n-1+n)/(n+1)=n/2(1+2+3+4+5+6+⋅⋅⋅+n−1+n)/(n+1)=n/2
Linear table element deletion: ListDelete(&L,i,&e)
Initial conditions: the linear list L already exists, 1≤i≤ListLength(L)
Operation result: delete the i-th data element of L, and return its value with e, and decrease the length of L by one
Algorithm thinking:
① Determine whether the deletion position i is legal (legal value 1≤i≤n)
② Keep the element to be deleted in e
③ Move the i+1th to nth elements one position forward in sequence
④ The length of the table is reduced by 1, and the deletion is successful and returns OK
C++:
C:
Algorithm analysis: The analysis here is very similar to the insertion of linear table elements,
( 1 + 2 + 3 + 4 + 5 + 6 + ⋅ ⋅ ⋅ + n − 1 ) / n = ( n − 1 ) / 2 (1+ 2+3+4+5+6+···+n-1)/n=(n-1)/2(1+2+3+4+5+6+⋅⋅⋅+n−1)/n=(n−1)/2
Sequence summary:
advantage:
· High storage density (storage occupied by the node itself/storage occupied by the node structure)
Can randomly access any element in the table
shortcoming:
· When inserting and deleting an element, a large number of elements need to be moved
· Waste of storage space
It belongs to the form of static storage, and the data elements cannot be freely expanded