[Data structure] - Detailed explanation of sequence table

Hello everyone! After we learn dynamic memory management, we can write a sequence table to manage data! ! !

Understanding the sequence table:

Linear table is 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 sequential table is a linear table saved in the form of an array in computer memory. The sequential storage of a linear table refers to using a set of storage units with consecutive addresses to sequentially store each element in the linear table so that the linear table is logically adjacent. The data elements are stored in adjacent physical storage units, that is, the logical adjacent relationship between data elements is reflected through the adjacent relationship of physical storage of data elements. A linear table using a sequential storage structure is usually called a sequential table. A sequence table stores the nodes in the table in sequence in a set of storage units with consecutive addresses in the computer memory.

Insert image description here

The static sequence table has a fixed size like an array. The dynamic sequence table can be expanded when the capacity is insufficient to achieve the effect of being able to store a large amount of data! ! !

1. First create a structure to represent the sequence list

typedef int DATE;//重命名顺序表的数据类型
typedef struct ArrayList {
    
    
	DATE* date;
	size_t size;//顺序表长度
	size_t capacity;//顺序表容量
}AL;

2. Display of all interfaces in the sequence table

void Init(AL* al);
void checkCapacity(AL* al);
void pushBack(AL* al, DATE info);
void pushFront(AL* al, DATE info);
void insertDate(AL* al,size_t pos, DATE info);
void printDate(AL* al);
void Erase(AL* al, size_t pos);
void PopBack(AL* al);
void PopFront(AL* al);
size_t FindDate(AL* al, DATE info);
void ExchangeDate(AL* al, size_t pos, DATE info);
void Deatory(AL* al);

3. Introduction to each interface function and implementation principle

1. Implementation of initialization function

void Init(AL* al)
{
    
    
	assert(al);
	al->size = 0;
	al->capacity = 4;//初始化容量为4
	DATE* tmp = (DATE*)malloc(sizeof(DATE) * al->capacity);
	if (tmp == NULL)
	{
    
    
		perror("malloc fail");
		exit(-1);
	}
	al->date = tmp;
}

The length of the initialization sequence table is 0 and the capacity is 4!

2. Check the implementation of the capacity function

void checkCapacity(AL* al)
{
    
    
	if (al->size == al->capacity)
	{
    
    
		DATE* tmp = (DATE*)realloc(al->date, sizeof(DATE) * al->capacity*2);
		if (tmp == NULL)
		{
    
    
			perror("realloc fail");
			exit(-1);
		}
		al->capacity *= 2;
		al->date = tmp;
		printf("扩容成功!\n");
	}
}

If the length is equal to the capacity, it means that the capacity needs to be expanded, so expand the capacity to 2 times the size.

3. Implementation of tail insertion function

void pushBack(AL* al, DATE info)
{
    
    
	assert(al);
	checkCapacity(al);
	al->date[al->size] = info;
	al->size++;
}

Be sure to check the capacity before each insertion.
Tail insertion means writing the value to be inserted at the end of size, and then adding one to the length.
Insert image description here

4. Implementation of head plug function

void pushFront(AL* al, DATE info)
{
    
    
	assert(al);
	checkCapacity(al);
	if (al->size == 0)
	{
    
    
		al->date[0] = info;
		al->size++;
	}
	else
	{
    
    
		size_t end = al->size;
		while (end)
		{
    
    
			al->date[end] = al->date[end-1];
			end--;
		}
		al->date[0] = info;
		al->size++;
	}
}

When inserting a piece of data, the following data must be moved to the back. The capacity may be exceeded during the movement, so expansion judgment is required when inserting.

Insert image description here

Moving method is as above

Insert image description here

5. Tail deletion function

void PopBack(AL* al)
{
    
    
    assert(ps);
	assert(al->size > 0);
	al->size--;
}

Decrease the length by one to delete the last data

6. Head deletion function

void PopFront(AL* al)
{
    
    
    assert(al->size > 0);
	int begin = 1;
	while (begin<al->size)
	{
    
    
		al->date[begin - 1] = al->date[begin];
		begin++;
     }
	al->size--;
}

The moving sequence method is as follows:
Insert image description here
define a variable begin=1, first move data 2 to the position of data 1, the corresponding operation is
al->date[begin - 1] = al->date[begin]; and then begin++, Move data 3 to the position of data 2 and data 4 to the position of data 3 in sequence. The last time of the loop is to move data 5 to the position of data 4, that is, begin=4, al->size=5. Then the loop judgment condition is beginsize, and after the loop ends, al->size–
;

Insert image description here

7. Implementation of the function of deleting data at any position

void Erase(AL* al, size_t pos)
{
    
    
	assert(al);
	assert(pos >= 0 && pos <= al->size);
	if (al->size == 0)
	{
    
    
		printf("暂无数据!!\n");
		return;
	}
	size_t end = pos;
	while (end<al->size-1)
	{
    
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/a1a63c6776c142eeb77e15536b8f9a53.png#pic_center)

		al->date[end] = al->date[end + 1];
		end++;
	}
	al->size--;
}

To delete a piece of data, all the elements after this position must be moved forward by one position
. Since the subscripts are represented by size_t, one must grasp the unsigned -1 and 0 loop conditions to compare sizes when deleting the head.

If we want to delete number 3, and then move the data after data 3 forward, the first step is to move data 4 to the position of data 3, and define a variable end=pos=2; the corresponding operation is al->date[end ] = al->date[end+1];, and then end++; moves data 5 to the beginning of data 4. The last loop is to move data 5 to data 4, that is, end is finally equal to 3, al->size=5, then the loop judgment condition is end< al->size-1, and the end of the loop will be al->size– ;

Insert image description here

8. Implementation of the function of inserting data at any position

void insertDate(AL* al, size_t pos, DATE info)
{
    
    
	assert(al);
	assert(pos >= 0 && pos <= al->size);
	checkCapacity(al);
	int end = al->size;
	while (end > pos)
	{
    
    
		al->date[end] = al->date[end - 1];
		end--;
	}
	al->date[pos] = info;
	al->size++;
}

Since the subscript Yi class is represented by size_t, one must grasp the situation when unsigned -1 and 0 loop conditions are compared when inserting the header.

Insert image description here

Inserting at any position requires moving the insertion position and subsequent data backward one position at a time!

9. Improvement of head plug deletion and head deletion and tail deletion functions

After we have written arbitrary insertion and arbitrary deletion, we can improve the head plug deletion and head deletion and tail deletion functions and directly call the arbitrary insertion and arbitrary deletion functions in their function bodies.

void pushFront(AL* al, DATE info)
{
    
    
	assert(al);
	checkCapacity(al);
	if (al->size == 0)
	{
    
    
		al->date[0] = info;
		al->size++;
	}
	else
	{
    
    
		insertDate(al, 0, info);
	}
}
void pushBack(AL* al, DATE info)
{
    
    
	assert(al);
	checkCapacity(al);
	insertDate(al, al->size, info);
}
void PopBack(AL* al)
{
    
    
	assert(al);
	if (al->size == 0)
	{
    
    
		printf("暂无数据!!\n");
		return;
	}
	Erase(al, al->size);

}
void PopFront(AL* al)
{
    
    
	assert(al);
	if (al->size == 0)
	{
    
    
		printf("暂无数据!!\n");
		return;
	}
	Erase(al, 0);
}

Head insertion is to call the insert function to insert at the 0 position.
Tail insertion is to call the insert function to insert at the size position.
Head deletion is to call the Erase function to delete the 0 position.
Tail deletion is to call the Erase function to delete the size position.

10. Implementation of search data function

size_t FindDate(AL* al, DATE info)
{
    
    
	assert(al);
	for (size_t i = 0; i < al->size; i++)
	{
    
    
		if (al->date[i] == info)
			return i;
	}
	return -1;
}

Convenience sequence table in turn, if the data you need to find is found, return its subscript, otherwise return -1

11. Modify data

void ExchangeDate(AL* al, size_t pos, DATE info)
{
    
    
	assert(al);
	assert(pos >= 0 && pos <= al->size);
	al->date[pos] = info;
}

First check whether the data to be modified exists, and then modify it.
It is usually used in conjunction with the search function.

Insert image description here

12. Destruction sequence table

Since the sequence table opens up the heap area memory, we must release the allocated memory after using the sequence table!

void Deatory(AL* al)
{
    
    
	assert(al);
	free(al->date);
	al->date=NULL;
	al->capacity = al->size = 0;
}

Destroy a sequence table, set the capacity of the sequence table to 0, set the number of valid data in the sequence table to 0, and release the dynamically allocated memory space pointed by the date pointer. Since the dynamically allocated memory space is released, all p The space pointed to is not initialized, and date becomes a wild pointer. In order to prevent wild pointers, date is set to a null pointer.

The sharing of the data structure part - the sequence table ends here, thank you all for browsing! ! !

Guess you like

Origin blog.csdn.net/m0_71214261/article/details/133419521