Beginning of sequence

Insert image description here

Welcome to my: world

I hope the author's article will be helpful to you. Please correct me if there are any deficiencies. Let's learn and communicate together!


Introduction to linear tables

Baidu: Linear tables are the most basic, simplest, and most commonly used data structure. A linear list is a type of data structure. A linear list is a finite sequence of n data elements with the same characteristics.

  • 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 list , 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 linear tables are physically stored, they are usually stored in the form of arrays and linked structures.

![Insert image description here](https://img-blog.csdnimg.cn/407892b043c9486db9b64ff8f8d330a0.png


Sequence table definition

The sequence table is a linear structure that uses a storage unit with a continuous physical address to store the data structure in sequence. Generally, array storage is used; the addition, deletion, checking, and modification of data are completed on the array;

Sequence lists can be divided into:
1. Static sequence lists: use fixed-length arrays to store elements;

#define N 100
typedef int SLDateType;
//定义静态顺序表
typedef struct SeqList
{
    
    
	SLDateType a[N]; //固定数组大小,N的值无法改变
	int size;        //数组有效的个数
	
}SeqList;

2. Dynamic sequence table: Use dynamically opened array storage;

typedef int SLDateType;
//定动态义顺序表
typedef struct SeqList
{
    
    
	SLDateType* a;//指向动态数组的指针
	int size;     //数组的有效数据
	int capacity; //空间大小
}SeqList;

Initialization of dynamic sequence table

The initialization sequence table uses dynamically allocated array space to construct an empty linear table.

//初始化
void SeqListInit(SeqList* ps)
{
    
    
	//用 malloc申请一块空间
	ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 4);
	if (ps->a== NULL)//判断是否申请空间成功
	{
    
    
		perror("malloc");
		exit(-1);
	}
	
	ps->capacity = 4;//将顺序表的最大长度设为 4
	ps->size = 0; //将顺序表的当前长度设为 0

}

For the malloc function to apply for dynamic memory space, you can read my other blog on dynamic memory space management for a detailed explanation;

tail plug

End insertion is to insert an element after the last element

  • There are three situations for tail insertion:
    the first situation is that there is no space in the sequence table at all, so use assert to solve it; the
    second situation is that the capacity space we created is full, and it needs to be increased before inserting later; the third situation is that the capacity space we created is full, and the capacity needs to be increased before inserting later; the
    third situation is that there is no space at all in the sequence table, and assert is used to solve the problem. If there is enough space, just insert data directly;
void SeqListPushBack(SeqList* ps, SLDateType x)
{
    
    
	//每次进来判断依次满了要扩容
	if (ps->size  == ps->capacity)
	{
    
    
		//realloc函数是专门用来增容的,以两倍的增容
		SLDateType* tem = (SLDateType*)realloc(ps->a, ps->capacity * 2  * sizeof(SLDateType));
		if (tem == NULL)//判断是否增容成功
		{
    
    
			perror("realloc");
			exit(-1);
		}
		ps->a = tem;
		ps->capacity *= 2;//空间大小以两倍增容
	}

	ps->a[ps->size] = x;//运用下标存储要插入的值
	ps->size++;//尾插成功则有效数据就加 1
}

Regarding the realloc function to adjust the dynamically applied memory space, the detailed explanation can be found in my other blog: Dynamic Memory Space Management , its detailed explanation must be understood! Very important! !

Head plug

Sequential tables require data to be stored continuously and must be stored from the beginning. Therefore, for sequence tables, if you want to implement head insertion, you need to move the data backward. You cannot move from front to back. If you move from front to back, the subsequent data will be overwritten.
Insert image description here

void SeqListPushFront(SeqList* ps, SLDateType x) {
    
    

	//每次进来判断依次满了要扩容
	if (ps->size == ps->capacity)
	{
    
    
		//realloc函数是专门用来增容的,以两倍的增容
		SLDateType* tem = (SLDateType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDateType));
		if (tem == NULL)//判断是否增容成功
		{
    
    
			perror("realloc");
			exit(-1);
		}
		ps->a = tem;
		ps->capacity *= 2;//空间大小以两倍增容
	}
	//从后往前式的往后移动一个元素
	int end = ps->size - 1;
	while (end>=0)
	{
    
    
		ps->a[end+1] = ps->a[end];
		--end;
	}

	ps->a[0] = x;//插入首元素
	ps->size++;//头插成功有效元素加1
}

At this time, you will look back and find that if the code when the capacity is to be increased is almost the same, we can write a separate function for the capacity increase to determine whether the capacity needs to be increased:

Cheak determines whether to increase capacity

void Cheak(SeqList*ps)
{
    
    
	//每次进来判断依次满了要扩容
	if (ps->size == ps->capacity)
	{
    
    
		//realloc函数是专门用来增容的,以两倍的增容
		SLDateType* tem = (SLDateType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDateType));
		if (tem == NULL)//判断是否增容成功
		{
    
    
			perror("realloc");
			exit(-1);
		}
		ps->a = tem;
		ps->capacity *= 2;//空间大小以两倍增容
	}
}

At this time, the tail plug and head plug are written like this:

Head plug:

void SeqListPushFront(SeqList* ps, SLDateType x) {
    
    
	Cheak(ps);//判断增容
	//从后往前式的往后移动一个元素
	int end = ps->size - 1;
	while (end>=0)
	{
    
    
		ps->a[end+1] = ps->a[end];
		--end;
	}

	ps->a[0] = x;//插入首元素
	ps->size++;//头插成功有效元素加1
}

Tail plug:

void SeqListPushBack(SeqList* ps, SLDateType x)
{
    
    
	Cheak(ps);//判断增容

	ps->a[ps->size] = x;//运用下标存储要插入的值
	ps->size++;//尾插成功则有效数据就加 1
}

Tail deletion:

Tail deletion of the sequence table is relatively simple, just use size–;

void SeqListPopBack(SeqList* ps)
{
    
    
	//当顺序表中无元素,不会进行尾删
	if (ps->size == 0)
	{
    
    
		printf("size越界访问");
		exit(-1);
	}

	ps->size--;
}

Header deletion:

Head deletion can be understood as: directly covering the second element from front to back;

//头删
void SeqListPopFront(SeqList* ps)
{
    
    
	
	assert(ps->size > 0);

	//删减
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
    
    
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

Print

Print out the elements in the sequence list;

void SeqListPrint(SeqList* ps) {
    
    

	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
    
    
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

Insert x before pos position

You need to know that pos is the element subscript. After finding the pos position, then move all the elements behind it backward by one element, and then insert the x to be inserted into the pos position;

void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
    
    
	//检查pos位置是否在顺序表里面
	assert(pos >= 0 && pos <= ps->size);
	Cheak(ps);//判断是否增容
	//找到有效数据元素的下标
	int end = ps->size - 1;
	//往后移
	while (end>=pos)
	{
    
    
		ps->a[end+1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;//空出pos位后插入
	ps->size++;
}

注意:SeqListInsert这个函数可以代替尾插或头插;

Delete the value of pos position

To delete the data at the specified location, we still have to limit the location of pos. The restriction part is different from SeqListInsert in that because there is no valid data at the psl->size position, the deleted position cannot be psl->size!

void SeqListErase(SeqList* ps, int pos) {
    
    
	//检查pos位置是否在顺序表里面
	assert(pos >= 0&&pos< ps->size);
	//找到pos位置的下一个
	int begain = pos + 1;
	
	while (begain < ps->size)
	{
    
    
		ps->a[begain - 1] = ps->a[begain];
		begain++;
	}
	ps->size--;

}

注意:SeqListErase这个函数可以代替尾删或头删;

look up

//查找返回其下标,否则返回-1;
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;
 
}

Revise

Modify the value of pos position

//修改pos位置的值,pos是其下标
void SLModify(SL* ps, int pos, SLDatatype x)  
{
    
    
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
 
	ps->a[pos] = x;
 
}

Look at the results of running the code:
Insert image description here
the last one is:

destroy

If you apply for dynamic memory memory space, you must remember to destroy it, because dynamic memory space will not be actively released unless the program ends, otherwise there may be a risk of memory leakage;

//销毁
void SeqListDestroy(SeqList* ps)
{
    
    
	//释放
	free(ps);
	ps->a = NULL;
	ps->capacity = 0;
	ps->size = 0;

}

At the end: thanks for the support

What I also want to tell you is:
---------- Go all out for the process and be indifferent to the results. This
is also what I say to myself.

Guess you like

Origin blog.csdn.net/m0_66780695/article/details/132380622