# Sequence table

## 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. However, the physical structure is not necessarily continuous. When the linear table is stored physically, it is usually stored in the form of array and chain structure.

But today's blog only talks about the sequence table

## Sequential table (essentially array)

### Concept and structure

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.

### The sequence table can generally be divided into:

#### 1. Static sequence table: use fixed length array to store elements.

```#pragma once

//It is convenient to change the size of the array
#define N 100

typedef int SLDataType; //This will be easy to modify

//Static sequence table
typedef struct SeqList
{
SLDataType a[N];
SLDataType size;//Indicates how many data are stored in the array
}SL;

void SeqListPushBack(SL* ps, SLDataType x);
```

The static feature is not to allow insertion when it is full. The disadvantage is that we don't know how much space is appropriate, waste when it is large and "crime" when it is small, so there is a dynamic sequence table

#### 2. Dynamic sequence table: use dynamic array storage.

Since they are all dynamic, there is no need for the space size N. We can use the pointer

```//It is convenient to change the size of the array
//#define N 100

typedef int SLDataType; //This will be easy to modify

//Dynamic sequence table
typedef struct SeqList
{
SLDataType* a;
int size;//Indicates how many data are stored in the array
int capacity;//How much space can the array actually hold data
}SL;

void SeqListPushBack(SL* ps, SLDataType x);
```

#### Interface function (here I teach you to close the pit, otherwise sometimes you don't know how to die (the difference between value transfer and address transfer))

##### Sequence table initialization SeqListInit
###### pass by value

A caveat here is that vs13 is different from vs19. vs13 can run without initialization, while vs19sl can't run without initialization. I'll put the figure below

Since the of the argument cannot be passed to the formal parameter, we will pass the address

```//Sequence table initialization
void SeqListInit(SL* ps)
{
ps->a = NULL;
ps->size = ps->capacity = 0;
}
```

#### Tail interpolation function SeqListPushBack

```//Tail insertion
void SeqListPushBack(SL* ps, SLDataType x)
{
if (ps->size == ps->capacity)
{
//There's no room at all
//Capacity expansion when the space is full
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
if (tmp == NULL)
{
printf("Development failure\n");//Failed to open up successfully
exit(-1);//Abnormal end
}
//After successful capacity expansion
ps->a = tmp;//Give him the new address
ps->capacity = newcapacity;//Give him the capacity

}
//Enough space
ps->a[ps->size] = x;
ps->size++;
}
```

But sometimes it's a waste of time to debug to see how our interface is written, so we have to write a print function

#### Sequence table printing function SeqListPrint

```//Sequence table printing
void seqListPrint(SL* ps)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
```

We can basically see this step as a successful start of the sequence table. Now we need to destroy the sequence table. In fact, we know that the last is the destruction of the sequence table, but we can realize it here (you can understand it as the smallest system of single chip microcomputer or the version of micro star)

#### Sequence table destruction function seqlistdestroy

```//Sequence table destruction
void seqListDestory(SL* ps)//Is to free memory and prevent memory overflow
{
free(ps->a);
ps->a = NULL;
ps->capacity = ps->size = 0;
}
```

When the minimum system board is ready, we will add modules one by one

#### Tail deletion function SeqListPopBack

tender

```//Tail deletion
void SeqListPopBack(SL* ps)
{
//Gentle approach
if (ps->size > 0)
{
ps->size--;
}
}
```

Rough (I, a big man, prefer to be rough and straightforward)

```//Tail deletion
void SeqListPopBack(SL* ps)
{
Gentle approach
//if (ps->size > 0)
//{
//	ps->size--;
//}
//Rough
assert(ps->size > 0);//It doesn't matter if you assert that it's not true and report an error directly
ps->size--;
}
```

Before writing the header insert, let's think about it. If you want to insert, you must consider whether you need to expand the capacity. Then it is heavier than the expansion in the previous tail insert, so you can extract it and write a function separately

#### Sequence table check capacity function SeqListCheckCapacity

```//Sequence table check capacity
void SeqListCheckCapacity(SL* ps)
{
if (ps->size == ps->capacity)
{
//There's no room at all
//Capacity expansion when the space is full
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
if (tmp == NULL)
{
printf("Development failure\n");//Failed to open up successfully
exit(-1);//Abnormal end
}
//After successful capacity expansion
ps->a = tmp;//Give him the new address
ps->capacity = newcapacity;//Give him the capacity
}
}
```

Then you can easily expand the capacity by checking the capacity with that

```//Head insert
void SeqListPushFront(SL* ps, SLDataType x)
{
//Check capacity increase
SeqListCheckCapacity(ps);
//Mobile data
int end = ps->size - 1;
while (end>=0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;
}
```

```//Header deletion
void SeqListPopFront(SL* ps)
{
assert(ps->size>0);
int begin = 1;
while (begin<ps->size)
{
ps->a[begin-1] = ps->a[begin];
begin++;
}
ps->size--;
}
```

#### Sequence table lookup function SeqListFind

```//Sequential table lookup function
int SeqListFind(SL* ps, SLDataType x)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
return i;
}
return -1;
}
```

#### Sequential table insert function SeqListInsert

```//Sequential table insert function
void SeqListInsert(SL* ps, int pos, SLDataType x)
{
//Assertion does not end directly in scope
assert(pos>=0 && pos<=ps->size);
//Check expansion
SeqListCheckCapacity(ps);
//Mobile data
int end = ps->size - 1;
while (pos<=end)
{
ps->a[end + 1] = ps->a[end];
end--;
}
//Then give the data to the current location
ps->a[pos] = x;
ps->size++;
}
```

Therefore, there is no need to write the head insert and tail insert. You can call the insert function directly

#### Sequence table delete function SeqListErase

```//Sequential table deletion function
void SeqListErase(SL* ps, int pos)
{
//Assertion does not end directly in scope
assert(pos >= 0 && pos < ps->size);
//When deleting, you do not need to consider capacity expansion, but directly move the data
int begin = pos;
while (begin+1<ps->size)
{
ps->a[begin] = ps->a[begin + 1];
begin++;
}
ps->size--;
}
```

Therefore, header deletion and tail deletion can be reused

## Exercises

### Example 1 Removing Elements

Let's analyze the problem first. He has requirements for space complexity and no requirements for time complexity

```int removeElement(int* nums, int numsSize, int val){
int i = 0;
int* cur = nums;
for(i = 0;i<numsSize;i++)
{
if(val ^ nums[i])
{
*cur++ = nums[i];
}
}
return cur-nums;
}
```

### Example 2 Remove duplicates from an ordered array

We can't look at it empty. We have to draw a picture to solve it. The problem directly determines the space. It won't give you an additional array, so we can only solve it with multiple pointers

Brain simulation, a positioning pointer, two cursor pointers, should be able to solve

```int removeDuplicates(int* nums, int numsSize){
if(numsSize == 0)//Empty array jump out
return 0;
int* cur = nums;//Positioning pointer
int* tail = nums+1;//Cursor tail pointer
while(tail<nums+numsSize)
{
{
tail++;
}
else
{
cur++;
tail++;
}
}
*cur = *head;//The last one is forced to be assigned regardless of equality
cur++;
return (cur-nums);
}
```

### Example 3 Merge two ordered arrays

```void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
int* p1 = nums1+m-1;
int* p2 = nums2+n-1;
int* cur = nums1+m+n-1;
while(p1>=nums1 && p2>=nums2)
{
*cur-- = *p1>*p2 ? *p1-- : *p2--;//ternary operator
}
while(p2>=nums2)
{
*cur-- = *p2--;
}
}
```

Posted by azul85 on Fri, 15 Oct 2021 16:18:52 -0700