Sequence table of data structure

Posted by adv on Thu, 30 Dec 2021 04:35:16 +0100

Linear table

  1. 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 table, linked list, stack, queue, string
  2. A linear table is logically a linear structure, that is, a continuous straight line. But in physical structure It is not necessarily continuous. When a linear table is stored physically, it is usually stored in the form of array and chain structure.

Concept and structure of sequence table

Sequential table is a linear structure in which data elements are stored in sequence with a storage unit with continuous physical addresses. Generally, array storage is used. Complete the addition, deletion, query and modification of data on the array.

Sequence table can be divided into static sequence table (using fixed length array to store elements) and dynamic sequence table (using dynamic array to store elements). In order to improve the flexibility of sequence table, we usually use dynamic sequence table.

Function realization of sequence table

First create three files

  • Create seqlist H represents header file (storing function declaration)
  • Create seqlist C represents function file (storing each function file)
  • Create test C stands for test file (help test function)

Define sequence table

Create the following structure in the header file

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;		//Dynamic array
	size_t size;		//Number of arrays stored
	size_t capacity;	//Capacity of the array
}SeqList;

Renaming int here is convenient for modifying the data types stored in the sequential table later

Sequence table initialization

void SeqListInit(SeqList* ps)
{
	assert(ps);			//Assert to prevent the file from passing null pointers, and the header file assert h
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

The effect is as follows

Before modification

After modification

Sequence table printing

Print all data in the array in order

void SeqListPrint(SeqList* ps)
{
	assert(ps);
	size_t i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (i == ps->size - 1)
		{
			printf("%d", ps->a[i]);
		}
		else
		{
			printf("%d-->", ps->a[i]);
		}
	}
	printf("\n");
}

End of sequence table

Before tail inserting, first check whether the array is full. If it is full, increase the capacity, and then tail insert the data and increase the storage capacity by one

So how to increase capacity?

First judge whether the number of stored data in the array is equal to the capacity of the array. If so, increase the capacity
Then judge whether the capacity of the array is 0. If it is 0, give it 4 spaces, otherwise double the capacity

void SeqListCheckCapcity(SeqList* ps)
{
	assert(ps);

	//Check whether it is full, and increase the capacity when it is full
	if (ps->size == ps->capacity)
	{
		size_t newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->a = (SLDateType*)realloc(ps->a, newcapacity*sizeof(SeqList));
		if (ps->a == NULL)
		{
			printf("Capacity increase failed\n");
			return;
		}
		ps->capacity = newcapacity;
	}
}
void SeqListPushBack(SeqList* ps, SLDateType x)
{
	assert(ps);
	SeqListCheckCapcity(ps);
	ps->a[ps->size] = x;//Tail insertion
	ps->size++;//Storage + 1
}

testing

This function has been implemented

Note: after each function is implemented, try to test it to ensure that the function can be implemented. If the program is written and tested again, it is not easy to find the source of the error

Sequential tail deletion

Tail deletion is much simpler, just size-1

Some people will ask, isn't the data without deletion code?
When we access, we will only access size data, and then the data will not be accessed, which is tantamount to deletion. When inserting data, the data will be overwritten by the new data, so you only need size-1

void SeqListPopBack(SeqList* ps)
{
	assert(ps->size > 0);		//You must ensure that there is data in the array
	assert(ps);
	ps->size--;
}

testing:

Sequential header interpolation

Idea:

  • The head plug is the same as the tail plug, and it is necessary to detect whether the capacity needs to be increased
  • Then move all the data back one bit
  • Finally, insert the data
void SeqListPushFront(SeqList* ps, SLDateType x)
{
	assert(ps);
	SeqListCheckCapcity(ps);
	//All data moves back one bit
	int end = ps->size;
	while (end)
	{
		ps->a[end] = ps->a[end-1];
		end--;
	}
	//insert data
	ps->a[0] = x;
	//Storage + 1
	ps->size++;
}

testing:

Sequential header deletion

Header deletion is to move the data after the first bit forward one bit and reduce the size by one

void SeqListPopFront(SeqList* ps)
{
	assert(ps);
	assert(ps->size > 0);
	//The subscript that records the last bit of data
	int end = ps->size - 1;
	int i = 0;
	//Move position
	while (end)
	{
		ps->a[i] = ps->a[i + 1];
		end--;
		i++;
	}
	ps->size--;
}

testing:

Find the specified element

Idea:

  • Traversal sequence table
  • Return subscript found, otherwise - 1 is returned
int SeqListFind(SeqList* ps, SLDateType x)
{
	assert(ps);
	//Traversal sequence table
	for (size_t i = 0; i < ps->size; i++)
	{
		if (x == ps->a[i])
			return i;//Return subscript
	}
	return -1;
}

Insert at the specified location

Idea:

  • Pass in the location subscript and the data to insert
  • Move the position and its subsequent data back one bit
  • size+1
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x)
{
	assert(ps);
	//The insertion position must be within the capacity
	assert(pos < ps->size);
	//Check whether capacity increase is required
	SeqListCheckCapcity(ps);
	int end = ps->size;
	for (size_t i = end; i > pos; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[pos] = x;
	ps->size++;
}

test

Delete specified location

Idea:

  • Move the data after the specified position forward by one bit
  • size-1
void SeqListErase(SeqList* ps, size_t pos)
{
	assert(ps);
	int end = ps->size;
	//Move position
	for (size_t i = pos; i < end; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

test

Destruction sequence table

void SeqListDestory(SeqList* ps)
{
	assert(ps);
	//Free up space
	if (ps->a)
	{
		free(ps->a);
	}
	ps->size = ps->capacity = 0;
}

summary

SeqList.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;		//Dynamic array
	size_t size;		//Number of arrays stored
	size_t capacity;	//Capacity of the array
}SeqList;

// Data management: addition, deletion, query and modification 
void SeqListInit(SeqList* ps);
//Print
void SeqListPrint(SeqList* ps);
//Tail insertion
void SeqListPushBack(SeqList* ps, SLDateType x);
//Tail deletion
void SeqListPopBack(SeqList* ps);
//Head insert
void SeqListPushFront(SeqList* ps, SLDateType x);
//Header deletion
void SeqListPopFront(SeqList* ps);
// Sequential table lookup
int SeqListFind(SeqList* ps, SLDateType x);
// The sequence table inserts an x at the pos position
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x);
// The sequence table deletes the value of pos position
void SeqListErase(SeqList* ps, size_t pos);
//Destroy
void SeqListDestory(SeqList* ps);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void SeqListInit(SeqList* ps)
{
	assert(ps);			//Assert to prevent the file from passing null pointers, and the header file assert h
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

void SeqListPrint(SeqList* ps)
{
	assert(ps);
	size_t i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (i == ps->size - 1)
		{
			printf("%d", ps->a[i]);
		}
		else
		{
			printf("%d-->", ps->a[i]);
		}
	}
	printf("\n");
}

void SeqListCheckCapcity(SeqList* ps)
{
	assert(ps);

	//Check whether it is full, and increase the capacity when it is full
	if (ps->size == ps->capacity)
	{
		size_t newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->a = (SLDateType*)realloc(ps->a, newcapacity*sizeof(SeqList));
		if (ps->a == NULL)
		{
			printf("Capacity increase failed\n");
			return;
		}
		ps->capacity = newcapacity;
	}
}

void SeqListPushBack(SeqList* ps, SLDateType x)
{
	assert(ps);
	SeqListCheckCapcity(ps);
	ps->a[ps->size] = x;//Tail insertion
	ps->size++;//Storage + 1
}

void SeqListPopBack(SeqList* ps)
{
	assert(ps->size > 0);//You must ensure that there is data in the array
	assert(ps);
	ps->size--;
}

void SeqListPushFront(SeqList* ps, SLDateType x)
{
	assert(ps);
	SeqListCheckCapcity(ps);
	//All data moves back one bit
	int end = ps->size;
	while (end)
	{
		ps->a[end] = ps->a[end-1];
		end--;
	}
	//insert data
	ps->a[0] = x;
	//Storage + 1
	ps->size++;
}

void SeqListPopFront(SeqList* ps)
{
	assert(ps);
	assert(ps->size > 0);
	//The subscript that records the last bit of data
	int end = ps->size - 1;
	int i = 0;
	//Move position
	while (end)
	{
		ps->a[i] = ps->a[i + 1];
		end--;
		i++;
	}
	ps->size--;
}

// Sequential table lookup
int SeqListFind(SeqList* ps, SLDateType x)
{
	assert(ps);
	//Traversal sequence table
	for (size_t i = 0; i < ps->size; i++)
	{
		if (x == ps->a[i])
			return i;//Return subscript
	}
	return -1;
}

// The sequence table inserts an x at the pos position
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x)
{
	assert(ps);
	//The insertion position must be within the capacity
	assert(pos < ps->size);
	//Check whether capacity increase is required
	SeqListCheckCapcity(ps);
	int end = ps->size;
	for (size_t i = end; i > pos; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[pos] = x;
	ps->size++;
}

// The sequence table deletes the value of pos position
void SeqListErase(SeqList* ps, size_t pos)
{
	assert(ps);
	int end = ps->size;
	//Move position
	for (size_t i = pos; i < end; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

void SeqListDestory(SeqList* ps)
{
	assert(ps);
	if (ps->a)
	{
		free(ps->a);
	}
	ps->size = ps->capacity = 0;
}

Topics: data structure