Data Structure Part 1: Sequence Table Analysis and Implementation

foreword

  A linear list is a finite sequence of n data elements with the same properties. A linear table is a data structure widely used in practice. Common linear tables: sequence table, linked list, stack, queue, string... A linear table is logically a linear structure, that is to say, a continuous straight line. However, the physical structure is not necessarily continuous. When the linear table is physically stored, it is usually stored in the form of an array and a chain structure. Today we are going to explain one of the sequence tables,

concept and structure

  The sequence table is a linear structure in which data elements are sequentially stored in a storage unit with continuous physical addresses, and is generally stored in an array. Add, delete, check and modify data on the array.

Analysis and realization of various functions

Creation of sequence table

  We need to create several variables to store the data we need. First of all, we definitely need an array. Here, in order to improve the space utilization, I have adopted a dynamic opening method to realize the sequence table, so we also need a variable sz to mark our How much data has been stored, and another variable to mark the current capacity capacity. (Because the method chosen here is not to add only one space after it is full, but to add multiple spaces at once, so it is necessary to record the current capacity and compare it with sz to see if the space is full)

typedef struct SeqList
{
    
    
	SLDataType* data;
	int sz;
	int capacity;
}SL;

initialization

  Initialize all data to empty for subsequent operations.

void InitSeqList(SL* ps)
{
    
    
	ps->data = NULL;
	ps->sz = 0;
	ps->capacity = 0;
}

capacity increase

  At the beginning, the available space is 0, so we need to open up space first so that we can store data.

void AddCapacity(SL* ps)
{
    
    
	//增容
	if (ps->sz == ps->capacity)
	{
    
    
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* pc = (SLDataType*)realloc(ps->data, sizeof(SLDataType) * newcapacity);
		if (pc == NULL)
		{
    
    
			perror("SeqListPushBack");
		}
		ps->data = pc;
		ps->capacity = newcapacity;
	}
}

  When ps->sz == ps->capacity, that is, the number of elements currently stored is equal to the current maximum capacity, which means that the space is already full, so the space is opened. As for SLDataType is the type of element, I redefine int as it here, so that we can modify the type of element in the future, and can achieve the effect of changing all.

tail plug

  Insert a new element at the end of the list.

void SeqListPushBack(SL* ps, SLDataType x)
{
    
    
	AddCapacity(ps);
	ps->data[ps->sz] = x;
	ps->sz++;
}

  Because a new element needs to be added, and we don't know whether the current linear table is full, so we need to judge whether we need to increase the capacity when we first come in. We need to put the elements to be inserted at the end, and add 1 to sz (the variable that records the number of elements).

tail delete

  Here I write two judgment methods, both of which can be used. If you want to use assert, remember to add the header file <assert.h>. This is to avoid the wrong operation that the sequence table is already empty and we continue to delete.

void SeqListPopback(SL* ps)
{
    
    
	//assert(ps->sz > 0);
	if (ps->sz > 0)
	{
    
    
		ps->sz--;
	}
}

  There is no need to delete it here. When we access this element, we access it through subscripts. For example, the subscript of the last element is ps->sz-1, we only need to make sz-1, and the variable sz that records the number of elements can be reduced by 1, and at the same time, it can not access the last element. as shown in the picture
insert image description here

Print

  To help us display the content of our current stored data on the screen.

void SeqListPrint(SL* ps)
{
    
    
	int i = 0;
	for (i = 0; i < ps->sz; i++)
	{
    
    
		printf("%d ", ps->data[i]);
	}
	printf("\n");
}

  Just output one by one from beginning to end.

plug

  Insert an element at the beginning of the sequence list.

void SeqListPushFront(SL* ps, SLDataType x)
{
    
    
	AddCapacity(ps);
	int end = ps->sz - 1;
	while (end >= 0)
	{
    
    
		ps->data[end + 1] = ps->data[end];
		end--;
	}
	ps->data[0] = x;
	ps->sz++;
}

  Similarly, this is also a new element, and we also need to judge whether it is necessary to increase the capacity. We want to insert an element at the beginning, so because of the nature of the sequence table, we must first move all elements back one element to make room for the first element. We just need to start from the end and move back one space one by one.

head delete

  Delete the first element.


void SeqListPopFront(SL* ps)
{
    
    
	if (ps->sz > 0)
	{
    
    
		int front = 1;
		while (front < ps->sz)
		{
    
    
			ps->data[front - 1] = ps->data[front];
			front++;
		}
		ps->sz--;
	}
}

  Because it is a deletion, we need to judge whether the sequence table is empty. If it is empty, it will not be deleted. This only needs to start from the second element and cover one by one forward. The second element covers the first element, and the third element covers the second element...

look up

  Find the subscript of an element, if not, it will show that it does not exist.

int SeqListFind(SL* ps, SLDataType x)
{
    
    
	int front = 0;
	while (front < ps->sz)
	{
    
    
		if (ps->data[front] == x)
		{
    
    
			return front;
		}
		front++;
	}
	printf("元素不存在\n");
	return -1;
}

  Starting from the first element, compare them one by one, and return the subscript if they are equal. If no equal display is found until the end, it does not exist.

Insert at position pos

  Insert an element at a certain position, which is implemented here before the pos position.

void SeqListInsert(SL* ps, int pos, SLDataType x)
{
    
    
	AddCapacity(ps);//增容
	assert(pos > 0 && pos <= ps->sz);//判断用户所输入的位置是否越界
	pos -= 1;               //转化为对应的下标
	int end = ps->sz - 1;  
	while (pos <= end)   //一直将下标为pos位置的元素挪完
	{
    
    
		ps->data[end + 1] = ps->data[end];   //将元素从后一个一个往后挪
		end--;
	}
	ps->data[pos] = x;
	ps->sz++;
}

  Because the array starts from 0, we need to insert the element at the second position, which is actually stored in ps->data[1]. There is a detailed introduction in the code, so I won't say much here.

Delete at pos position

  Delete an element at a certain position.

void SeqListErase(SL* ps, int pos)
{
    
    
	int end = pos - 1;      //将end与下标相对应,指向第pos个元素的下标
	if (pos > ps->sz)
	{
    
    
		printf("该位置没有元素\n");
	}
	if (pos > 0 && pos <= ps->sz)   //保证顺序表里要有元素,并且删除的元素位置必须小于最后一个元素的位置
	{
    
    
		while (end < ps->sz - 1)      //不断往前覆盖,当然也可以一开始不转化为下标,pos指向的是对应元素的下一个元素,直接向前覆盖也可以
		{
    
    
			ps->data[end] = ps->data[end + 1];
			end++;
		}
		ps->sz--;
	}
}

  I also wrote detailed comments on the above code, so I won’t talk about it here. If you have any questions, you can send a private message or leave a message in the comment area.

destroy

  The dynamically opened space needs to be released when not in use to prevent memory leaks.

void SeqListDestory(SL* ps)
{
    
    
	free(ps->data);
	ps->data = NULL;
	ps->sz = 0;
	ps->capacity = 0;
}

  There is nothing to say about this, everyone will understand after looking at it, I will put all the code later, divided into three files, one is the definition of the structure and the declaration of the function, one is the implementation of the function, and the other is to There is no problem with the function of the test function.

Code

SeqList.h

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define SLDataType int
//顺序表的创建
typedef struct SeqList
{
    
    
	SLDataType* data;
	int sz;
	int capacity;
}SL;

//初始化
void InitSeqList(SL* ps);

//增容
void AddCapacity(SL* ps);

//尾插
void SeqListPushBack(SL* ps, SLDataType x);

//尾删
void SeqListPopback(SL* ps);

//打印
void SeqListPrint(SL* ps);

//头插
void SeqListPushFront(SL* ps, SLDataType x);

//头删
void SeqListPopFront(SL* ps);

//查找
int SeqListFind(SL* ps, SLDataType x);

//在pos位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x);

//在pos位置删除
void SeqListErase(SL* ps, int pos);

//销毁
void SeqListDestory(SL* ps);

SeqList.c

#include"SeqList.h"
void InitSeqList(SL* ps)
{
    
    
	ps->data = NULL;
	ps->sz = 0;
	ps->capacity = 0;
}

void AddCapacity(SL* ps)
{
    
    
	//增容
	if (ps->sz == ps->capacity)
	{
    
    
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* pc = (SLDataType*)realloc(ps->data, sizeof(SLDataType) * newcapacity);
		if (pc == NULL)
		{
    
    
			perror("SeqListPushBack");
		}
		ps->data = pc;
		ps->capacity = newcapacity;
	}
}

void SeqListPushBack(SL* ps, SLDataType x)
{
    
    
	AddCapacity(ps);
	ps->data[ps->sz] = x;
	ps->sz++;
}

void SeqListPopback(SL* ps)
{
    
    
	//assert(ps->sz > 0);
	if (ps->sz > 0)
	{
    
    
		ps->sz--;
	}
}

void SeqListPrint(SL* ps)
{
    
    
	int i = 0;
	for (i = 0; i < ps->sz; i++)
	{
    
    
		printf("%d ", ps->data[i]);
	}
	printf("\n");
}

void SeqListPushFront(SL* ps, SLDataType x)
{
    
    
	AddCapacity(ps);
	int end = ps->sz - 1;
	while (end >= 0)
	{
    
    
		ps->data[end + 1] = ps->data[end];
		end--;
	}
	ps->data[0] = x;
	ps->sz++;
}

void SeqListPopFront(SL* ps)
{
    
    
	if (ps->sz > 0)
	{
    
    
		int front = 1;
		while (front < ps->sz)
		{
    
    
			ps->data[front - 1] = ps->data[front];
			front++;
		}
		ps->sz--;
	}
}

int SeqListFind(SL* ps, SLDataType x)
{
    
    
	int front = 0;
	while (front < ps->sz)
	{
    
    
		if (ps->data[front] == x)
		{
    
    
			return front;
		}
		front++;
	}
	printf("元素不存在\n");
	return -1;
}

void SeqListInsert(SL* ps, int pos, SLDataType x)
{
    
    
	AddCapacity(ps);
	assert(pos > 0 && pos <= ps->sz);
	pos -= 1;               //转化为对应的下标
	int end = ps->sz - 1;  
	while (pos <= end)   //一直将下标为pos位置的元素挪完
	{
    
    
		ps->data[end + 1] = ps->data[end];   //将元素从后一个一个往后挪
		end--;
	}
	ps->data[pos] = x;
	ps->sz++;
}

void SeqListErase(SL* ps, int pos)
{
    
    
	int end = pos - 1;      //将end与下标相对应,指向第pos个元素的下标
	if (pos > ps->sz)
	{
    
    
		printf("该位置没有元素\n");
	}
	if (pos > 0 && pos <= ps->sz)   //保证顺序表里要有元素,并且删除的元素位置必须小于最后一个元素的位置
	{
    
    
		while (end < ps->sz - 1)      //不断往前覆盖,当然也可以一开始不转化为下标,pos指向的是对应元素的下一个元素,直接向前覆盖也可以
		{
    
    
			ps->data[end] = ps->data[end + 1];
			end++;
		}
		ps->sz--;
	}
}

void SeqListDestory(SL* ps)
{
    
    
	free(ps->data);
	ps->data = NULL;
	ps->sz = 0;
	ps->capacity = 0;
}

test.c

#include"SeqList.h"
void test1()
{
    
    
	//测试功能
	SL s1;
	InitSeqList(&s1);
	SeqListPushBack(&s1, 1); //测试:尾插
	SeqListPushBack(&s1, 2);
	SeqListPushBack(&s1, 3);
	SeqListPrint(&s1);

	SeqListPopback(&s1);//测试:尾删及顺序表为空时,继续尾删会不会报错
	SeqListPopback(&s1);
	SeqListPopback(&s1);
	SeqListPopback(&s1);

	SeqListPushBack(&s1, 1);//测试:头插
	SeqListPushFront(&s1, 2);
	SeqListPushFront(&s1, 3);
	SeqListPrint(&s1);

	SeqListPopFront(&s1);  //测试:头删

	int ret = SeqListFind(&s1, 1);  //测试:查找
	if (ret != -1)
	{
    
    
		printf("找到了,下标为:>%d\n", ret);
	}

	SeqListInsert(&s1, 1, 5);//测试:在1位置插入元素5
	SeqListPrint(&s1);

	SeqListErase(&s1, 1); // 测试:删除1位置的元素
	SeqListPrint(&s1);
	SeqListErase(&s1, 4);// 测试:删除4位置的元素
	SeqListPrint(&s1);

	SeqListDestory(&s1);//销毁

}
int main()
{
    
    
	test1();
	return 0;
}

Summarize

  This is the first time to write the content of data structure. This is the first article. I will continue to write articles on linked lists, stacks, queues, etc. in the future. I hope it can be helpful to everyone. If you think it is good, you can give it a thumbs up. Thank you. La! !
  Here I don’t have the modification function, so I can give you some suggestions. You only need to use the search function to find the subscript of the element that needs to be modified, and then directly overwrite it. For details, you can refer to the address book I wrote before for related implementations . module, will not be available for reference.
  The time of study is always so short, and I feel more honored to be with you. I am willing to make progress together with you and look forward to the future. So this is the end of this issue, let's see you next time.

Guess you like

Origin blog.csdn.net/qq_62321047/article/details/129383262