In-depth understanding of data structure (2) --- the realization of the sequence table

sequence table

The sequence table is a kind of linear structure----sequential storage structure

This structure occupies a contiguous space in memory (similar to an array)

A sequence table can be implemented in two ways:

  • One is to use static array to achieve,
#define NUM 100
typedef struct SeqList{
    
    
    int a[NUM];
    int size;//表长
}SeqList;

NUM is the size of the array, which is the number of elements that can be placed in the sequence table.

We can use size to record how many elements have been placed in the array at a certain moment.

  • One is to use dynamic development to achieve
typedef struct SeqList {
    
    
	SeqListType* list;
	int size;//表长
	int capacity;
}SeqList;

The use of pointers and dynamic memory development can flexibly control the size of the space

Also use size to record how many elements have been stored

Capacity is similar to NUM in static arrays, the difference is that Capacity can be expanded or reduced as needed.

Comparison of the two: We can't determine how much space we actually need to use before we use it, so we use the method of dynamic development, which can flexibly control the size of the space.

The functions that need to be implemented in the sequence table:

The sequence table can achieve the following functions:

//函数的声明
//顺序表的初始化----SeqListInit

//尾插一个元素----SeqListPushBack
//尾删一个元素----SeqListPopBack

//头插一个元素----SeqListPushFront
//头删一个元素----SeqListPopFront

//任何位置的元素插入----SeqListInsert
//任何位置的元素删除----SeqListErase

//检查容量----SeqListCheckCapacity

//销毁顺序表----SeqListDeStroy

Next, we will implement these functions in turn

Initialization of the sequence table

void SeqListInit(SeqList* psl)
{
    
    
	assert(psl);
	psl->capacity = 0;
	psl->size = 0;
	psl->list = NULL;
}

We can start with an initial value for capacity, or we can assign the initial value to 0 like this

The capacity of the sequence table

Note: When we operate a sequence table, we need to pay attention to whether the capacity of the sequence table is full. If the capacity of the sequence table is full, we need to expand the capacity so that we can continue to add elements to the sequence table.

void SeqListCheckCapacity(SeqList* psl)
{
    
    
	assert(psl);//判断psl是否为空指针

	if (psl->size == psl->capacity)
	{
    
    
		int newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
        //如果capacity的值为0(只有初始化的时候才可能为0),那么就将capacity 的值赋为4。
        //如果caoacity的值不为0,那么就让容量翻倍。

		SeqListType* tmp = (SeqListType*)realloc(psl->list, sizeof(SeqListType) * newcapacity);
		if (tmp == NULL)
		{
    
    
			printf("realloc:fail\n");
			exit(-1);
		}
		else
		{
    
    
			psl->list = tmp;
			psl->capacity = newcapacity;
		}

	}

}

When the value of size and capacity are the same, it means that the capacity of the sequence table is full, and we need to expand the capacity

Note: We need to judge whether the expansion is successful (judging whether tmp is a null pointer).

Add elements to the sequence list

add element at the end of the sequence list

Note: 1. Every time you add an element to the sequence table, you need to check the capacity of the sequence table.

2. Every time you add an element, you need to increase the value of size by 1.

void SeqListPushBack(SeqList* psl, SeqListType x)
{
    
    
	assert(psl);
	SeqListCheckCapacity(psl);
	psl->list[psl->size] = x;
	psl->size++;
}

When adding elements to the tail, it psl->list[psl->size]is the address we want to assign. Since the value of size is easy to get, the operation of adding elements to the tail is very simple.

Add elements to the head of the sequence list

void SeqListPushFront(SeqList* psl, SeqListType x)
{
    
    
	assert(psl);

	SeqListCheckCapacity(psl);
	
	int begin = psl->size;
	while (begin > 0)
	{
    
    
		psl->list[begin] = psl->list[begin - 1];
		begin--;
	}
	psl->list[0] = x;
	psl->size++;
	
}

insert image description here

Add an element at the specified position in the sequence table

void SeqListInsert(SeqList* psl, size_t pos, SeqListType x)
{
    
    
	assert(psl);
	if (pos > psl->size)
	{
    
    
		printf("越界");
	}
	SeqListCheckCapacity(psl);//检查容量
	size_t begin = psl->size;
	while (begin > pos)
	{
    
    
		psl->list[begin] = psl->list[begin - 1];
		begin--;
		}
	psl->list[pos] = x;
	psl->size++;
	
}

Adding an element at a specified position is very similar to adding an element to the head of a sequence list.

insert image description here

However, before inserting elements, we need to determine whether the passed parameters meet the conditions

insert image description here

Different insertion positions have different results :

insert image description here

delete an element from the sequence list

It should be noted that the value of size needs to be decremented by 1 every time an element is deleted in the sequence table.

delete the element at the end of the sequence list

//尾删一个元素
void SeqListPopBack(SeqList* psl)
{
    
    
	assert(psl);

	if (psl->size > 0)
	{
    
    
		psl->size--;
	}

}

To delete the elements at the end, we only need to reduce the table length (size) by 1, because we use size to record how many elements there are in the sequence table. It is equivalent to removing the last element.

delete the element at the head of the sequence list

//头删一个元素
void SeqListPopFront(SeqList* psl)
{
    
    
	assert(psl);

	int begin = 1;
	while (begin < psl->size)
	{
    
    
		psl->list[begin-1] = psl->list[begin];
		begin++;
	}
	psl->size--;
}

To delete the element at the head of the element table, you only need to start from the second element in the sequence table, cover it forward in turn, until the value of the last element, cover the position of the penultimate element, and then let the table length (size ) minus 1 to complete the deletion of the head element.

insert image description here

Deletes the element at the specified position in the sequence table

void SeqListErase(SeqList* psl, size_t pos)
{
    
    

	assert(psl);
	assert(pos < psl->size);
	
		size_t begin = pos+1;
		while (begin < psl->size)
		{
    
    
			psl->list[begin-1] = psl->list[begin];
			begin++;
		}
		psl->size--;
	

}

The method of deleting the element at the specified position is similar to the method of deleting the head element:

insert image description here

Destruction order table

Since we are using the sequence table implemented by the method of dynamic memory development, we need to release the dynamically opened space in the end.

void SeqListDeStroy(SeqList* psl)
{
	assert(psl);

	free(psl->list);
	psl->capacity = 0;
	psl->size = 0;
	psl->list = NULL;
}

Complete implementation of sequence table

head FileSeqList.h

#pragma once
//顺序表

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//结构的声明
//有两种顺寻标的声明,一种是静态的---以数组的形式
//另一种是动态的----动态内存开辟,第一种方式开辟出来的空间可能会不足,,也可能会浪费,所以我们采用动态内存开辟的方式

typedef int SeqListType;

typedef struct SeqList {
    
    
	SeqListType* list;
	int size;
	int capacity;
}SeqList;

//一个顺序表要实现的功能有:在任何一个位置插入一个元素,
//在任何一个位置删除一个元素,修改元素,查找元素


//函数的声明

//顺序表的初始化
void SeqListInit(SeqList* psl);

//尾插一个元素
void SeqListPushBack(SeqList* psl, SeqListType x);
//尾删一个元素
void SeqListPopBack(SeqList* psl);
//头插一个元素
void SeqListPushFront(SeqList* psl, SeqListType x);

//头删一个元素
void SeqListPopFront(SeqList* psl);

//任何位置的元素插入
void SeqListInsert(SeqList* psl, size_t pos, SeqListType x);
//任何位置的元素删除
void SeqListErase(SeqList* psl, size_t pos);
//检查容量
void SeqListCheckCapacity(SeqList* psl);

//销毁顺序表
void SeqListDeStroy(SeqList* pal);

//打印顺序表的内容
void SeqListPrint(SeqList* psl);

Source FileSeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
//函数实现
#include"SeqList.h"

//顺序表的初始化
void SeqListInit(SeqList* psl)
{
	assert(psl);
	psl->capacity = 0;
	psl->size = 0;
	psl->list = NULL;
}



//检查容量
void SeqListCheckCapacity(SeqList* psl)
{
	assert(psl);

	if (psl->size == psl->capacity)
	{


		int newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;

		SeqListType* tmp = (SeqListType*)realloc(psl->list, sizeof(SeqListType) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc:fail\n");
			exit(-1);
		}
		else
		{
			psl->list = tmp;
			psl->capacity = newcapacity;

		}

	}

}
//尾插一个元素
void SeqListPushBack(SeqList* psl, SeqListType x)
{
	assert(psl);


	SeqListCheckCapacity(psl);

	psl->list[psl->size] = x;
	psl->size++;

}


//尾删一个元素
void SeqListPopBack(SeqList* psl)
{
	assert(psl);

	if (psl->size > 0)
	{
		psl->size--;
	}

}


//头插一个元素
void SeqListPushFront(SeqList* psl, SeqListType x)
{
	assert(psl);

	SeqListCheckCapacity(psl);
	
	int begin = psl->size;
	while (begin > 0)
	{
		psl->list[begin] = psl->list[begin - 1];
		begin--;
	}
	psl->list[0] = x;
	psl->size++;
	

}

//头删一个元素
void SeqListPopFront(SeqList* psl)
{
	assert(psl);

	int begin = 1;
	while (begin < psl->size)
	{
		psl->list[begin-1] = psl->list[begin];
		begin++;
	}
	psl->size--;

}

//任何位置的元素插入
void SeqListInsert(SeqList* psl, size_t pos, SeqListType x)
{
	assert(psl);
	if (pos > psl->size)
	{

		printf("越界");

	}

	SeqListCheckCapacity(psl);
	
	
	
		size_t begin = psl->size;
		while (begin > pos)
		{
			psl->list[begin] = psl->list[begin - 1];
			begin--;
		}
		psl->list[pos] = x;
		psl->size++;
	
}

//任何位置的元素删除
void SeqListErase(SeqList* psl, size_t pos)
{

	assert(psl);
	assert(pos < psl->size);
	
		size_t begin = pos+1;
		while (begin < psl->size)
		{
			psl->list[begin-1] = psl->list[begin];
			begin++;
		}
		psl->size--;
	

}

//销毁顺序表
void SeqListDeStroy(SeqList* psl)
{
	assert(psl);

	free(psl->list);
	psl->capacity = 0;
	psl->size = 0;
	psl->list = NULL;
}

//打印顺序表的内容
void SeqListPrint(SeqList* psl)
{
	assert(psl);

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

Source Filetest.c

void menu()
{
    
    
	printf("********************************\n");
	printf("***  1.尾插      2.尾删      ***\n");
	printf("***  3.头插      4.头删      ***\n");
	printf("***  5.指定插入  6.指定删除  ***\n");
	printf("***  7.查看     -1.退出      ***\n");
	printf("********************************\n");
}


int main()
{
    
    

	SeqList data;
	InitSeqList(&data);
	int option = -1;
	do {
    
    
		menu();
		printf("请选择您想要进行的操作:>");
		scanf("%d", &option);
		SeqListType val = 0;
		size_t pos = 0;

		switch (option)
		{
    
    
		case 1:
		
			printf("请输入您想要插入的数据:>");
			scanf("%d", &val);
			SeqListPushBack(&data, val);
		

			break;
		case 2:

			SeqListPopBack(&data);
			break;
		case 3:
			printf("请输入您想要插入的数据:>");
			scanf("%d", &val);

			SeqListPushFront(&data, val);

			break;

		case 4:

			SeqListPopFront(&data);
			break;

		case 5:
			printf("请输入你想要插入的数据:>");
			scanf("%d", &val);
			printf("请输入你想要插入的位置:>");
			scanf("%d", &pos);
			SeqListInsert(&data, pos, val);

			break;

		case 6:
			printf("请输入您想要删除的位置:>");
			scanf("%d", &pos);
			SeqListErase(&data, pos);
			break;

		case 7:
	
			SeqListPrint(&data);
			break;
		case -1:
			printf("退出程序\n");
			return 0;
			break;

		default:
			printf("请重新选择\n");
			break;
		}


	} while (option);


	test2(&data);


	return 0;
}

summary

  • When operating the sequence table, you need to be clear about these three properties of the sequence table:
  1. The starting location of the storage space
  2. Maximum capacity of the sequence table
  3. the current length of the sequence table
  • We can add and delete elements to the sequence table by using the current length and starting position of the sequence table.
    However, it should be noted that the table length will increase by 1 after each element is added, and the table length will decrease by 1 after each element is deleted. .

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324517864&siteId=291194637