Personal homepage: Welcome everyone --> Populus euphratica under the desert
Guys, you are so beautiful
If you find the article helpful
You can support bloggers with one click
Every ounce of your concern is the driving force for me to persevere
☄: Focus of this issue: Sequence table in linear table
I hope you all have a happy study and work every day.
1. Create a multi-file project
4. Open up dynamic space (increase capacity)
5. Sequential table footer insertion
6. Tail deletion of sequence table
7. The header of the sequence table
8. Delete the header of the sequence table
11, the search of the sequence table
12. Data modification of the sequence table
13. The deletion and modification part under the supplement
14 Optimization of head deletion and tail deletion and head insertion and tail insertion
16.Free open up space and print
18: Regarding the knowledge used:
What is a 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 table: sequence table, linked list, stack, queue, string... Linear table is logically linear structure, that is to say a continuous straight line . However, the physical structure is not necessarily continuous. When a linear table is physically stored, it is usually stored in the form of an array and a chain structure.
What is a sequence table?
The sequence table is a linear structure in which data elements are sequentially stored in a segment of storage units with consecutive physical addresses, generally using array storage. Complete data addition, deletion, search and modification on the array. The sequence table can generally be divided into:
1. Static order table: use a fixed-length array to store elements. (fixed length)
2. Dynamic sequence table: use dynamically developed array storage. (Can be expanded)
1. Create a multi-file project
We want to implement the sequence table through multiple files.
To have a header file, and function implementation. C files and test source files.
Among them, in the header file, it is necessary to prevent the repeated inclusion of the header file, and the reference of the header file.
2. Create a structure
We want to create a structure to store and perform sequence table related operations.
typedef int SLdataType; typedef struct Seqlist { SLdataType *a; int size; int capicity; }SL;
We created the struct and renamed the struct,
Then we need to use dynamically allocated memory, so we have to have a pointer variable to store the dynamically allocated array.
Then we have the number of elements that have been stored, and the actual capacity.
Finally, we have to consider what array do we store? is integer, char, float? These are uncertain, so we have to redefine the type so that we can maintain the array more conveniently.
3. Initialize the array
We have an array, so the first thing to do is to initialize the array.
void SLInit(SL* ps) { assert(ps); ps->a = NULL; ps->capicity = ps->size = 0; }
We need to know that the declaration of the function should be placed in the header file (we won't go into details later), and the implementation of the function should be placed in the .c file.
Secondly, we need to carry out "preventive" programming of functions, which is to judge the "legality" of incoming function pointers.
4. Open up dynamic space (increase capacity)
Our all-important dynamic array isn't there yet?
We want to develop, then open through malloc or other ways?
After malloc is developed, the problem of capacity expansion must be considered, so it is not better for us to directly use realloc to develop .
So we open up like this:
void SLCheckCapaticy(SL *ps) { assert(ps); if (ps->size == ps->capicity) { //使用双目操作符让增容和初始化一个realloc函数实现。 int newCapicity = ps->capicity == 0 ? 4 : 2 * (ps->capicity); SLdataType * tmp = (SLdataType *)realloc(ps->a, sizeof(SLdataType)*newCapicity); if (NULL == tmp) { perror("realloc:"); exit(-1); } ps->a = tmp; ps->capicity = newCapicity; } }
In this way, a function can be used to realize the process of opening up space and increasing capacity.
5. Sequential table footer insertion
The implementation of the tail interpolation function is relatively simple, but one thing to pay attention to is to judge whether to increase the capacity.
void SLPushBack(SL* ps, SLdataType x) { assert(ps); SLCheckCapaticy(ps); ps->a[ps->size] = x; ps->size++; }
First judge whether the pointer of the function is empty, then judge whether to increase the capacity, and finally put the data directly.
6. Tail deletion of sequence table
When tail deletion, do we need to set the deleted value to 0 or -1?
The answer is no, because if the data was originally 0 or 1, then wouldn't it have changed?
So we just need to make -1 the number of elements in the structure.
void SLPopBack(SL *ps) { assert(ps); assert(ps->size); ps->size--; }
7. The header of the sequence table
The head insertion of the sequence table is to write at the position where the subscript is 0. First, we should put the subscript from 0 to the subscript as the size number.
According to moving backward a data-sized space, the space with the subscript 0 is freed up. So we have to move the data,
And, we need to move the data backwards from back to front.
We first create a variable as a subscript,
This subscript cannot be out of bounds, and the element of 0~size-1 needs to be accessed, which is the loop condition.
Then it is not to cross the boundary, but also to consider the problem of expansion.
Finally, put the element, size++, and that's it.
void SLPushFront(SL *ps, SLdataType x) { assert(ps); SLCheckCapaticy(ps); int end = ps->size - 1; while (end >= 0) { ps->a[end+1] = ps->a[end]; end--; } ps->a[0] = x; ps->size++; }
8. Delete the header of the sequence table
Header deletion is similar to header insertion, but it is a bit different and has more restrictions.
The first thing to do is to check if the pointer is empty.
Determine whether the number of elements is greater than or equal to 0 (also assert with assert)
Header deletion only requires element coverage, no element modification.
Move the element to cover. (elements are 0 to size-1, prevent forward out of bounds, constraints are 1 to szie -1)
void SLPopFront(SL *ps) { assert(ps); assert(ps->size); int begin = 1; while (begin < ps->size) { ps->a[begin - 1] = ps->a[begin]; begin++; } ps->size--; }
9. Insert anywhere
Parameters inserted at any position need one more subscript.
First, we need to determine whether the pointer and subscript are legal.
Secondly, we must consider whether it will cross the border and expand the capacity.
Data movement is then performed, with restrictions similar to header plugs. (pos to size -1, actually access pos to size)
Finally put the data, size++
void SLInsert(SL* ps, int pos, SLdataType x) { assert(ps); assert(pos >= 0 && pos <= ps->size); SLCheckCapaticy(ps); int end = ps->size - 1; while (end >= pos) { ps->a[end + 1] = ps->a[end]; end--; } ps->a[pos] = x; ps->size++; }
10. delete anywhere
Deleting arbitrary positions is the same as inserting parameters.
You don't need to consider expansion, but you need to consider moving forward
Data movement: Constraints are (pos to size-1, actual access pos to size)
Finally, put size--.
void SLErase(SL *ps, int pos) { assert(ps); assert(pos >= 0 && pos < ps->size); int begin = pos; while (begin < ps->size-1) { ps->a[begin] = ps->a[begin+1]; begin++; } ps->size--; }
11, the search of the sequence table
The code to find is very simple, you just need to traverse to find it.
It should be noted that what is returned is the subscript of the found data .
int SLFind(SL *ps, SLdataType x) { assert(ps); for (int i = 0; i < ps->size; i++) { if (ps->a[i] == x) { return i; } } return -1; }
12. Data modification of the sequence table
The modification is also very simple, we can directly overwrite the data .
Note that there are constraints on subscripting. 1
void SLModify(SL *ps, int pos, SLdataType x) { assert(ps); assert(pos >= 0 && pos < ps->size); ps->a[pos] = x; }
13. The deletion and modification part under the supplement
When we search and modify the sequence table, we can encapsulate it into a function when inputting data.
One thing to note is that the return value of the lookup function can be used as a condition for judgment and can be accessed as a chain .
void Find(SL *ps)//查找相关的函数 { printf("请输入要查找的数据:"); int a = 0; scanf("%d", &a); if (SLFind(ps, a) >= 0) { printf("找到了,下标是:%d\n", SLFind(ps, a)); SLPrint(ps); } else { printf("找不到\n"); } } void Modify(SL *ps)//修改相关的函数 { printf("要查找的数据和要替换的数据:"); int x = 0; int y = 0; scanf("%d%d", &x, &y); if (SLFind(ps, x) >= 0) { SLModify(ps, SLFind(ps, x), y); printf("修改成功\n"); SLPrint(ps); } else { printf("没找到:%d\n", x); } }
14 Optimization of head deletion and tail deletion and head insertion and tail insertion
We have already written about insertion at any position, so can we optimize head insertion and tail insertion and head deletion and tail deletion ?
Header:
void SLPushFront(SL *ps, SLdataType x) { //assert(ps); //SLCheckCapaticy(ps); //int end = ps->size - 1; //while (end >= 0) //{ // ps->a[end+1] = ps->a[end]; // end--; //} //ps->a[0] = x; //ps->size++; SLInsert(ps, 0, x);//从0下标插入 }
Tail plug:
void SLPushBack(SL* ps, SLdataType x) { assert(ps); SLCheckCapaticy(ps); ps->a[ps->size] = x; ps->size++; //SLInsert(ps, ps->size, x);//从size位置插入,不会越界 }
Header delete:
void SLPopFront(SL *ps) { assert(ps); assert(ps->size); int begin = 1; while (begin < ps->size) { ps->a[begin - 1] = ps->a[begin]; begin++; } ps->size--; //SLErase(ps, 0);//从0下标开始删 }
Tail deletion :
void SLPopBack(SL *ps) { assert(ps); assert(ps->size); ps->size--; //SLErase(ps, ps->size - 1);//删除size-1位置的数据 }
This is code reusability .
16.Free open up space and print
Nothing to say:
void SLPrint(SL *ps) { assert(ps); for (int i = 0; i < ps->size; i++) { printf("%d ", ps->a[i]); } printf(" %d", ps->size); printf("\n"); }
void SLDestory(SL *ps) { assert(ps); if (ps->a != NULL) { free(ps->a); ps->a = NULL; ps->capicity = ps->size = 0; } }
17: About the overall code
Seqlist.h file
#pragma once #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int SLdataType; typedef struct Seqlist { SLdataType *a; int size; int capicity; }SL; void SLInit(SL* ps);//初始化 void SLCheckCapaticy(SL *ps);//增容 void SLPrint(SL *ps);//打印 void SLDestory(SL *ps);//free空间 void SLPushBack(SL* ps,SLdataType x);//尾插 void SLPopBack(SL *ps);//尾删 void SLPushFront(SL *ps,SLdataType x);//头插 void SLPopFront(SL *ps);//头删 void SLInsert(SL* ps, int pos, SLdataType x);//任意位置插入 void SLErase(SL *ps, int pos);//任意位置删除 int SLFind(SL *ps, SLdataType x);//查找 void Find(SL *ps); void SLModify(SL *ps, int pos, SLdataType x);//修改 void Modify(SL *ps);
Seqlist.c file
#include "Seqlist.h" void SLPrint(SL *ps) { assert(ps); for (int i = 0; i < ps->size; i++) { printf("%d ", ps->a[i]); } printf(" %d", ps->size); printf("\n"); } void SLInit(SL* ps) { assert(ps); ps->a = NULL; ps->capicity = ps->size = 0; } void SLCheckCapaticy(SL *ps) { assert(ps); if (ps->size == ps->capicity) { int newCapicity = ps->capicity == 0 ? 4 : 2 * (ps->capicity); SLdataType * tmp = (SLdataType *)realloc(ps->a, sizeof(SLdataType)*newCapicity); if (NULL == tmp) { perror("realloc:"); exit(-1); } ps->a = tmp; ps->capicity = newCapicity; } } void SLPushBack(SL* ps, SLdataType x) { assert(ps); SLCheckCapaticy(ps); ps->a[ps->size] = x; ps->size++; //SLInsert(ps, ps->size, x); } void SLPushFront(SL *ps, SLdataType x) { //assert(ps); //SLCheckCapaticy(ps); //int end = ps->size - 1; //while (end >= 0) //{ // ps->a[end+1] = ps->a[end]; // end--; //} //ps->a[0] = x; //ps->size++; SLInsert(ps, 0, x); } void SLPopBack(SL *ps) { assert(ps); assert(ps->size); ps->size--; //SLErase(ps, ps->size - 1); } void SLPopFront(SL *ps) { assert(ps); assert(ps->size); int begin = 1; while (begin < ps->size) { ps->a[begin - 1] = ps->a[begin]; begin++; } ps->size--; //SLErase(ps, 0); } void SLDestory(SL *ps) { assert(ps); if (ps->a != NULL) { free(ps->a); ps->a = NULL; ps->capicity = ps->size = 0; } } void SLInsert(SL* ps, int pos, SLdataType x) { assert(ps); assert(pos >= 0 && pos <= ps->size); SLCheckCapaticy(ps); int end = ps->size - 1; while (end >= pos) { ps->a[end + 1] = ps->a[end]; end--; } ps->a[pos] = x; ps->size++; } void SLErase(SL *ps, int pos) { assert(ps); assert(pos >= 0 && pos < ps->size); int begin = pos; while (begin < ps->size-1) { ps->a[begin] = ps->a[begin+1]; begin++; } ps->size--; } int SLFind(SL *ps, SLdataType x) { assert(ps); for (int i = 0; i < ps->size; i++) { if (ps->a[i] == x) { return i; } } return -1; } void SLModify(SL *ps, int pos, SLdataType x) { assert(ps); assert(pos >= 0 && pos < ps->size); ps->a[pos] = x; }
18: Regarding the knowledge used:
Brothers who are not very clear about the following knowledge, you can click the link below, which is written by the editor himself, welcome to care~!
Pointer-related knowledge-----> Pointer knowledge
Knowledge of memory management -> Memory management
Structure related knowledge-------> Structure knowledge
Next notice:
The next issue will explain the call of the function stack frame
The next issue is a big one~! ~! ~!