1, Definition (logical structure) and basic operation (operation) of linear table
- Definition: a linear table is a finite sequence of n (n > = 0) data elements with the same data type, where n is the table length. When n = 0, the linear table is an empty table. If L is used to name the linear table, it is generally expressed as
L = (a1 , a2 , ... , ai , ai+1 , an)- The same indicates that the data types are the same, and each element occupies the same space
- Finite indicates that the number of elements in the table is limited
- Sequence indicates that the elements in the table have logical order, and the elements in the table have their order
- All elements in the table are data elements, and each element is a single element
- The elements in the table are abstract, that is, they only discuss the logical relationship between elements without considering what elements represent
- a1 is the only "first data element", which is called the header element
- an is the only "last data element", called the footer element
- Except for the first element, all other elements have only one direct precursor element
- Except for the last element, all other elements have only one direct successor element
- The i subscript indicates the number of data elements, starting from the first
Note: linear list is a logical structure, which represents the one-to-one adjacent relationship between elements, while sequential list and linked list are storage structures with different conceptual levels.
- Basic operation of linear table
- Initlist & initialize the table, build an empty linear table L, and allocate memory space
- Destroylist & destroy operation, destroy linear table, and free the memory space occupied by linear table L
- Listinsert (& L, i, e) insert operation, insert the specified element E at the ith position of table L
- ListDelete (&, i, & E) deletes the element at the ith position in Table L, and e returns the value of the deleted element
- LocateElem(L,e) searches by value and finds elements with given keyword values in L types of tables
- GetElem(L,i) searches by bit to get the value of the element at the ith position in table L
- Length(L) finds the table length and returns the length of linear table L, that is, the number of elements in the table
- PrintList(L) traverses the linear table
- Empty(L) determines whether it is an empty table
2, Definition of sequence table
1. Concept
-
Definition: the sequential storage of linear table is also called sequential table. It uses a group of storage units with continuous addresses to store the data elements in the linear table in turn, so that the two logically adjacent elements are also adjacent in physical location. The characteristic of sequence table is that the logical sequence is the same as its physical sequence.
-
Suppose that the storage starting position of linear table L is LOC (A), and sizeof (ElemType) is the storage space occupied by each element. The storage order of linear table L is shown in the following figure
-
Summary of characteristics
- Random access, that is, the ith element can be found in O(1) time
- The storage density is high, and each node only stores data elements
- Inconvenient to expand capacity (even if it can be expanded, the time complexity is high)
- It is inconvenient to insert and delete, and a large number of elements need to be moved
2. Realization
1. I nitialize
- Static allocation
#include <stdio.h> #define MAXSIZE 50 /* Define a maximum length of 50*/ #define ELemType int /* Suppose the data is int or something else*/ typedef struct{ ElemType data[MAXSIZE]; /* Using arrays to store data */ int length; /* Table length definition */ }SqList; /* Type definition of sequence table */ void InitList(SqList &L){. /* Implementation of static allocation sequence table */ for(int i = 0;i < MAXSIZE;i++) L.data[i] = 0; /* All elements default to 0 to prevent dirty data interference */ L.length = 0; /* Table length is 0 */ } void test(){ /* Test call method */ SqList L; /* Declare a sequence table */ InitList(L); /* Initialize linear table */ //...... } int main(){ test(); return 0; }
- Dynamic allocation
#include <stdio.h> #include <stdlib.h> #define INITSIZE 100 /* The size of the initialization table is 100*/ #define ELemType int typedef struct{ ElemType *data; /* data array */ int length; /* Table length */ int MaxSize; /* The current maximum table length is initialized to INITSIZE */ }SeqList; void InitList(SeqList &L){ /* Dynamically allocated memory initialization */ /* Use malloc function to apply for space of INITSIZE * sizeof(ELemType) to store ElemType data */ L.data = (ElemType*)malloc(INITSIZE * sizeof(ELemType)); L.length = 0; L.MaxSize = INITSIZE; /* The maximum length of initialization is the initialization length */ } /* Increase the maximum storage space length of the table */ void IncreaseSize(SeqList &L,int len){ ElemType *p = L.data; /* Backup data */ /* Apply for multi len space*/ L.data = (ElemType*)malloc((L.MaxSIze + len) * sizeof(ELemType)); /* Restore the backup data to the newly applied continuous space */ for(int i = 0; i < L.length; i++) L.data[i] = p[i]; L.MaxSize += len; /* The maximum surface length becomes larger len */ free(p); /* Release backup data p */ } void test(){ /* test method */ SeqList L; InitList(L); //...... int LengthToIncrease; IncreaseSize(L,LengthToIncrease); } int main(){ test(); return 0; }
II. insert
/* Based on static allocation */ bool ListInsert(SqList &L,int i,ELemType e){ if(i < 1 || i > L.length + 1) return false; if(L.length >= MAXSIZE) return false; for(int j = L.length;j >= i;j--) L.data[j] = L.data[j - 1]; L.data[i - 1] = e; L.length++; return true; } void test(){ SqList L; InitList(L); ListInsert(L,1,1); //1 ListInsert(L,2,2); //1,2 ListInsert(L,3,3); //1,2,3 ListInsert(L,1,4); //4,1,2,3 }
-
Time complexity of insertion operation
- Best O(1)
- Worst O(n)
- Average O(n)
-
Insert element moved forward from last
3. Delete
bool ListDelete(SqList &L,int i,ElemType *e){ if(i < 1 || i > L.length) return false; e = data[i - 1]; for(int j = i;j < L.length;j++) L.data[j - 1] = L.data[j]; L.length--; return true; } void test{ /* ...... */ int e = -1; ListDelete(L,3,e); }
- Time complexity
- Best O(1)
- Worst O(n)
- Average O(n)
- Delete moves the element back from the deletion position to the last one
4. Search
- Bitwise
/* Time complexity O(1) */ ElemType GetElem(SqList L,int i){ if(i < 1 || i > L.length) print("Wrong!\n"); return -1; else return L.data[i - 1]; }
- By value
int LocateElem(SeqList L,ElemType e){ for(int i = 0; i < L.length;i++){ if(L.data[i] == e) return (i + 1); } return 0; }
- Time complexity
- Best O(1)
- Worst O(n)
- Average O(n)
3, Chain representation of linear list
1. Definition and establishment
- Definition: single linked list is a data structure with chain access. A group of storage units with arbitrary address are used to store the data elements in the linear list. The data in the linked list is represented by nodes. The composition of each node is: element (image of data element) + pointer (indicating the storage location of subsequent elements). The element is the storage unit for storing data, and the pointer is the address data connecting each node.
- Advantages: large continuous space is not required, and it is convenient to change the capacity
- Disadvantages: it can not be accessed randomly. It takes a certain space to store the pointer
- code implementation
typedef struct LNode{ ElemType data; struct LNode *next; }LNode,*LinkList; /* LNode *L == LinkList L */ /* Both represent the first node. The former emphasizes the node, the latter emphasizes that L is a single linked list, and the latter has high readability */
- Initialize a single linked list without leading nodes
typedef struct LNode{ ELemType data; struct LNode *next; }LNode,LinkList; bool InitList(LinkList &L){ L = null; return true; }
- Initialize a single linked list of leading nodes
typedef struct LNode{ ELemType data; struct LNode *next; }LNode,LinkList; bool InitList(LinkList &L){ L = (LNode*)malloc(sizeof(LNode)); if(L == null) return false; L -> next = null; return true; }
2. Operation of linked list
- Insert by bit (leading node)
bool ListInsert(LinkList &L,int i,ELemType e){ if(i < 1) return false; LNode *p; int j = 0; p = L; while(p != NULL && j < i - 1){ p = p -> next; j++; } if(p == NULL) //i illegal return false; LNode *s = (LNode*)malloc(sizeof(LNode)); s -> data = e; s -> next = p -> next; p -> next = s; return true; }
- Insert by bit (leading node)
bool ListInsert(LinkList &L,int i,ELemType e){ if(i < 1) return false; if(i ==1){ LNode *s = (LNode*)malloc(sizeof(LNode)); s -> data = e; s -> next = L; L = s; return true; } LNode *p; int j = 1; p = L; while(p != NULL && j < i - 1){ p = p -> next; j++; } if(p == NULL) //i illegal return false; LNode *s = (LNode*)malloc(sizeof(LNode)); s -> data = e; s -> next = p -> next; p -> next = s; return true; }
- Specify the backward operation of the node
bool InsertNextNode(LNode *p,ElemType e){ if(p == NULL) return false; LNode *s = (LNode*)malloc(sizeof(LNode)); if(s == NULL)//memory allocation failed return false; s -> data = e; s -> next = p -> next; p -> next = s; return true; }
- Specify the forward operation of the node
bool InsertPriorNode(LNode *p,LNode *s){ if(p == NULL || s == NULL) return false; s -> next = p -> next; p -> next = s; ElemType temp = p -> data; p -> data = s -> data; s -> data = temp; return true; }
Unfinished to be continued