Linear table
- A linear list is a finite sequence of n data elements with the same characteristics. Linear table is a data structure widely used in practice. Common linear tables: sequential table, linked list, stack, queue, string
- A linear table is logically a linear structure, that is, a continuous straight line. But in physical structure It is not necessarily continuous. When a linear table is stored physically, it is usually stored in the form of array and chain structure.
Concept and structure of sequence table
Sequential table is a linear structure in which data elements are stored in sequence with a storage unit with continuous physical addresses. Generally, array storage is used. Complete the addition, deletion, query and modification of data on the array.
Sequence table can be divided into static sequence table (using fixed length array to store elements) and dynamic sequence table (using dynamic array to store elements). In order to improve the flexibility of sequence table, we usually use dynamic sequence table.
Function realization of sequence table
First create three files
- Create seqlist H represents header file (storing function declaration)
- Create seqlist C represents function file (storing each function file)
- Create test C stands for test file (help test function)
Define sequence table
Create the following structure in the header file
typedef int SLDateType; typedef struct SeqList { SLDateType* a; //Dynamic array size_t size; //Number of arrays stored size_t capacity; //Capacity of the array }SeqList;
Renaming int here is convenient for modifying the data types stored in the sequential table later
Sequence table initialization
void SeqListInit(SeqList* ps) { assert(ps); //Assert to prevent the file from passing null pointers, and the header file assert h ps->a = NULL; ps->capacity = ps->size = 0; }
The effect is as follows
Before modification
After modification
Sequence table printing
Print all data in the array in order
void SeqListPrint(SeqList* ps) { assert(ps); size_t i = 0; for (i = 0; i < ps->size; i++) { if (i == ps->size - 1) { printf("%d", ps->a[i]); } else { printf("%d-->", ps->a[i]); } } printf("\n"); }
End of sequence table
Before tail inserting, first check whether the array is full. If it is full, increase the capacity, and then tail insert the data and increase the storage capacity by one
So how to increase capacity?
First judge whether the number of stored data in the array is equal to the capacity of the array. If so, increase the capacity
Then judge whether the capacity of the array is 0. If it is 0, give it 4 spaces, otherwise double the capacity
void SeqListCheckCapcity(SeqList* ps) { assert(ps); //Check whether it is full, and increase the capacity when it is full if (ps->size == ps->capacity) { size_t newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; ps->a = (SLDateType*)realloc(ps->a, newcapacity*sizeof(SeqList)); if (ps->a == NULL) { printf("Capacity increase failed\n"); return; } ps->capacity = newcapacity; } } void SeqListPushBack(SeqList* ps, SLDateType x) { assert(ps); SeqListCheckCapcity(ps); ps->a[ps->size] = x;//Tail insertion ps->size++;//Storage + 1 }
testing
This function has been implemented
Note: after each function is implemented, try to test it to ensure that the function can be implemented. If the program is written and tested again, it is not easy to find the source of the error
Sequential tail deletion
Tail deletion is much simpler, just size-1
Some people will ask, isn't the data without deletion code?
When we access, we will only access size data, and then the data will not be accessed, which is tantamount to deletion. When inserting data, the data will be overwritten by the new data, so you only need size-1
void SeqListPopBack(SeqList* ps) { assert(ps->size > 0); //You must ensure that there is data in the array assert(ps); ps->size--; }
testing:
Sequential header interpolation
Idea:
- The head plug is the same as the tail plug, and it is necessary to detect whether the capacity needs to be increased
- Then move all the data back one bit
- Finally, insert the data
void SeqListPushFront(SeqList* ps, SLDateType x) { assert(ps); SeqListCheckCapcity(ps); //All data moves back one bit int end = ps->size; while (end) { ps->a[end] = ps->a[end-1]; end--; } //insert data ps->a[0] = x; //Storage + 1 ps->size++; }
testing:
Sequential header deletion
Header deletion is to move the data after the first bit forward one bit and reduce the size by one
void SeqListPopFront(SeqList* ps) { assert(ps); assert(ps->size > 0); //The subscript that records the last bit of data int end = ps->size - 1; int i = 0; //Move position while (end) { ps->a[i] = ps->a[i + 1]; end--; i++; } ps->size--; }
testing:
Find the specified element
Idea:
- Traversal sequence table
- Return subscript found, otherwise - 1 is returned
int SeqListFind(SeqList* ps, SLDateType x) { assert(ps); //Traversal sequence table for (size_t i = 0; i < ps->size; i++) { if (x == ps->a[i]) return i;//Return subscript } return -1; }
Insert at the specified location
Idea:
- Pass in the location subscript and the data to insert
- Move the position and its subsequent data back one bit
- size+1
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x) { assert(ps); //The insertion position must be within the capacity assert(pos < ps->size); //Check whether capacity increase is required SeqListCheckCapcity(ps); int end = ps->size; for (size_t i = end; i > pos; i--) { ps->a[i] = ps->a[i - 1]; } ps->a[pos] = x; ps->size++; }
test
Delete specified location
Idea:
- Move the data after the specified position forward by one bit
- size-1
void SeqListErase(SeqList* ps, size_t pos) { assert(ps); int end = ps->size; //Move position for (size_t i = pos; i < end; i++) { ps->a[i] = ps->a[i + 1]; } ps->size--; }
test
Destruction sequence table
void SeqListDestory(SeqList* ps) { assert(ps); //Free up space if (ps->a) { free(ps->a); } ps->size = ps->capacity = 0; }
summary
SeqList.h
#define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> typedef int SLDateType; typedef struct SeqList { SLDateType* a; //Dynamic array size_t size; //Number of arrays stored size_t capacity; //Capacity of the array }SeqList; // Data management: addition, deletion, query and modification void SeqListInit(SeqList* ps); //Print void SeqListPrint(SeqList* ps); //Tail insertion void SeqListPushBack(SeqList* ps, SLDateType x); //Tail deletion void SeqListPopBack(SeqList* ps); //Head insert void SeqListPushFront(SeqList* ps, SLDateType x); //Header deletion void SeqListPopFront(SeqList* ps); // Sequential table lookup int SeqListFind(SeqList* ps, SLDateType x); // The sequence table inserts an x at the pos position void SeqListInsert(SeqList* ps, size_t pos, SLDateType x); // The sequence table deletes the value of pos position void SeqListErase(SeqList* ps, size_t pos); //Destroy void SeqListDestory(SeqList* ps);
SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"SeqList.h" void SeqListInit(SeqList* ps) { assert(ps); //Assert to prevent the file from passing null pointers, and the header file assert h ps->a = NULL; ps->capacity = ps->size = 0; } void SeqListPrint(SeqList* ps) { assert(ps); size_t i = 0; for (i = 0; i < ps->size; i++) { if (i == ps->size - 1) { printf("%d", ps->a[i]); } else { printf("%d-->", ps->a[i]); } } printf("\n"); } void SeqListCheckCapcity(SeqList* ps) { assert(ps); //Check whether it is full, and increase the capacity when it is full if (ps->size == ps->capacity) { size_t newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; ps->a = (SLDateType*)realloc(ps->a, newcapacity*sizeof(SeqList)); if (ps->a == NULL) { printf("Capacity increase failed\n"); return; } ps->capacity = newcapacity; } } void SeqListPushBack(SeqList* ps, SLDateType x) { assert(ps); SeqListCheckCapcity(ps); ps->a[ps->size] = x;//Tail insertion ps->size++;//Storage + 1 } void SeqListPopBack(SeqList* ps) { assert(ps->size > 0);//You must ensure that there is data in the array assert(ps); ps->size--; } void SeqListPushFront(SeqList* ps, SLDateType x) { assert(ps); SeqListCheckCapcity(ps); //All data moves back one bit int end = ps->size; while (end) { ps->a[end] = ps->a[end-1]; end--; } //insert data ps->a[0] = x; //Storage + 1 ps->size++; } void SeqListPopFront(SeqList* ps) { assert(ps); assert(ps->size > 0); //The subscript that records the last bit of data int end = ps->size - 1; int i = 0; //Move position while (end) { ps->a[i] = ps->a[i + 1]; end--; i++; } ps->size--; } // Sequential table lookup int SeqListFind(SeqList* ps, SLDateType x) { assert(ps); //Traversal sequence table for (size_t i = 0; i < ps->size; i++) { if (x == ps->a[i]) return i;//Return subscript } return -1; } // The sequence table inserts an x at the pos position void SeqListInsert(SeqList* ps, size_t pos, SLDateType x) { assert(ps); //The insertion position must be within the capacity assert(pos < ps->size); //Check whether capacity increase is required SeqListCheckCapcity(ps); int end = ps->size; for (size_t i = end; i > pos; i--) { ps->a[i] = ps->a[i - 1]; } ps->a[pos] = x; ps->size++; } // The sequence table deletes the value of pos position void SeqListErase(SeqList* ps, size_t pos) { assert(ps); int end = ps->size; //Move position for (size_t i = pos; i < end; i++) { ps->a[i] = ps->a[i + 1]; } ps->size--; } void SeqListDestory(SeqList* ps) { assert(ps); if (ps->a) { free(ps->a); } ps->size = ps->capacity = 0; }