数据结构——顺序表实现

201 阅读3分钟

什么是顺序表

用【一段连续的物理空间】存储数据的线性结构。数据必须从第一个位置开始,连续存储.

一般采用数组存储。

image.png

顺序表的实现(C语言实现)

定义顺序表的结构体

#define N 100
typedef  int SLDataType;//先定顺序表中的数据是整型
//静态顺序表:N小可能存不下数据,N太大空间浪费,不实用
/*struct SeqList
{
	SLDataType a[N];//存储顺序表中数据的数组
	int size;    //当前已有的数据个数
};*/

//动态顺序表
typedef struct SeqList
{
	SLDataType* a;//指向动态开辟的空间
	int size;//已有的数据个数,顺序表规定:数据必须从第一个位置开始连续存储
	int capacity;//当前容量,当已有的数据量比容量大时,要扩容
}SL;

相关函数

顺序表的初始化和销毁

void SLInit(SL* seqlist)//顺序表初始化
{
	assert(seqlist);
	seqlist->capacity = 4;//初始容量设置
	SLDataType* tem = (SLDataType*)malloc(sizeof(SLDataType) * seqlist->capacity);
	if (tem == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	seqlist->a = tem;
	seqlist->size = 0;
}

void SLDestroy(SL* seqlist)//顺序表的销毁
{
	assert(seqlist);
	free(seqlist->a);
}

顺序表的增删查改

尾插与尾删

时间复杂度为O(1)

void SLPushBack(SL* seqlist, SLDataType x)//顺序表尾插
{
	assert(seqlist);
	SLCheckCapacity(seqlist);//用来检查是否需要扩容的函数,后面会实现
	seqlist->a[seqlist->size] = x;
	seqlist->size++;
}
void SLPopBack(SL* seqlist)//顺序表尾删
{
	assert(seqlist && seqlist->size > 0);//数据量必须大于0
	seqlist->size--;
}

头插与头删

时间复杂度为O(N)

顺序表头插.png

void SLPushFront(SL* seqlist, SLDataType x)//顺序表头插
{
	assert(seqlist);
	SLCheckCapacity(seqlist);//用来检查是否需要扩容的函数
	//从后往前 向后挪动数据
	int end = seqlist->size - 1;//下标从0开始,seqlist->size是最后一个数据的下一个位置
	while (end >= 0)
	{
		seqlist->a[end + 1] = seqlist->a[end];
		end--;
	}
	seqlist->a[0] = x;
	seqlist->size++;
}

顺序表头删.png

void SLPopFront(SL* seqlist)//顺序表头删
{
	assert(seqlist&&seqlist->size > 0);//数据量必须大于0
	//从前往后 向前挪动数据
	int begin = 0;
	while(begin <seqlist->size - 1)
	{
		seqlist->a[begin] = seqlist->a[begin+1];
		begin++;
	}
	seqlist->size--;
}

任意位置的插入和删除

image.png

void SLInsert(SL* seqlist, int pos, SLDataType x)//顺序表任意位置插入数据
{
	assert(seqlist);
	assert(pos >= 0 && pos <= seqlist->size);
	SLCheckCapacity(seqlist);
	//顺序表插入数据是(从后往前) 向后挪数据
	int end = seqlist->size - 1;
	while (end >= pos)
	{
		seqlist->a[end + 1] = seqlist->a[end];
		end--;
	}
	seqlist->a[pos] = x;
	seqlist->size++;
}

image.png

void SLErase(SL* seqlist, int pos)//顺序表删除任意位置的数据
{
	assert(seqlist && seqlist->size > 0);
	assert(pos >= 0 && pos < seqlist->size);
	//顺序表删除数据是(从前往后)向前挪数据
	int begin = pos;
	while (begin < seqlist->size - 1)
	{
		seqlist->a[begin] = seqlist->a[begin + 1];
		begin++;
	}
	seqlist->size--;
}

查找与修改

int SLSearch(SL* seqlist, SLDataType x) //顺序表中查找(返回下标)
{
	assert(seqlist);
	for (int i = 0; i < seqlist->size; i++)
	{
		if (x == seqlist->a[i])
			return i;
	}
	return -1;//没有找到返回-1
}

void SLModify(SL* seqlist, int pos, SLDataType x)//把pos位置的值修改成x
{
	assert(seqlist && pos >= 0 && pos < seqlist->size);
	seqlist->a[pos] = x;
}

其它函数

1 插入数据都需要检查容量是否足够

void SLCheckCapacity(SL* seqlist)
{
	assert(seqlist);
	if (seqlist->capacity == seqlist->size)//如果已有的数据个数=容量并且要继续插入,先扩容
	{
		int newcapacity = seqlist->capacity * 2;
		SLDataType* a = (SLDataType*)realloc(seqlist->a, newcapacity * sizeof(SLDataType));
		if (a == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		seqlist->a = a;
		seqlist->capacity *= 2;
	}
}

2 打印顺序表的数据

void SLPrint(SL* seqlist)//打印顺序表数据
{
	assert(seqlist);
	for (int i = 0; i < seqlist->size; i++)
	{
		printf("%d ", seqlist->a[i]);
	}
	putchar('\n');
}