Linear table☞Sequence table (7000 words detailed explanation)

  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. 

 

What is a linear table?

What is a sequence table?

1. Create a multi-file project

2. Create a structure

3. Initialize the array

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

9. Insert anywhere

10. delete anywhere

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

17: About the overall code

Seqlist.h file

Seqlist.c file

18: Regarding the knowledge used:

Next notice:


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~! ~! ~!

Guess you like

Origin blog.csdn.net/m0_64770095/article/details/124378435