(C语言)数据结构-线性表之动态定长顺序表(完整代码)

动态定长顺序表的基本操作

//初始化的顺序表L
ElemType* SeqListInit();
//销毁(释放)顺序表的空间
int SeqListDestory(SeqList* L);
//顺序表动态扩容
void CheckCapacity(SeqList* L);
//顺序表尾插
int SeqListPushBack(SeqList* L, ElemType x);
//顺序表尾删
int SeqListPopBack(SeqList* L);
//顺序表头插
int SeqListPushFront(SeqList* L, ElemType x);
//顺序表头删
int SeqListPopFront(SeqList* L);
//输出顺序表的内容
int SeqListPrint(SeqList* L);
//返回顺序表中元素的下标
int SeqListFind(SeqList* L, ElemType x);
//顺序表任意位置插入元素
int SeqListInsert(SeqList* L, size_t i, ElemType x);
//删除顺序表指定下标的元素
int SeqListErase(SeqList* L, size_t i);
//返回数据表中元素的个数
size_t SeqListSize(SeqList* L);
//修改指定位置元素的值
int SeqListAt(SeqList* L, size_t i, ElemType x);

完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define TRUE 1
#define FALSE 0
typedef int ElemType;

typedef struct SeqList
{
	ElemType* arr;		//用于指向动态开辟的数组空间
	size_t size;		//有效数据个数
	size_t capacity;	//容量大小
}SeqList;


//销毁(释放)顺序表的空间
int SeqListDestory(SeqList* L);
//顺序表动态扩容
void CheckCapacity(SeqList* L);
//顺序表尾插
int SeqListPushBack(SeqList* L, ElemType x);
//顺序表尾删
int SeqListPopBack(SeqList* L);
//顺序表头插
int SeqListPushFront(SeqList* L, ElemType x);
//顺序表头删
int SeqListPopFront(SeqList* L);
//输出顺序表的内容
int SeqListPrint(SeqList* L);
//返回顺序表中元素的下标
int SeqListFind(SeqList* L, ElemType x);
//顺序表任意位置插入元素
int SeqListInsert(SeqList* L, size_t i, ElemType x);
//删除顺序表指定下标的元素
int SeqListErase(SeqList* L, size_t i);
//返回数据表中元素的个数
size_t SeqListSize(SeqList* L);
//修改指定位置元素的值
int SeqListAt(SeqList* L, size_t i, ElemType x);



/***
*	函数名称:ElemType* SeqListInit()
*	函数功能:返回一个初始化的顺序表L
*	入口参数:none
*	出口参数:ElemType* L
*	返回类型:ElemType*
***/
SeqList* SeqListInit()
{
	SeqList* L;
	L = (SeqList*)malloc(sizeof(SeqList));
	L->arr = NULL;		//初始顺序表为空
	L->size = 0;		//初始数据个数为0
	L->capacity = 0;	//初始空间容量为0
	return L;
}

/***
*	函数名称:int SeqListDestory(SeqList* L)
*	函数功能:销毁(释放)顺序表的空间
*	入口参数:SeqList* L
*	出口参数:1
*	返回类型:int
***/
int SeqListDestory(SeqList* L)
{
	//assert() 断言 值为假(0)时终止程序执行
	assert(L != NULL);
	free(L->arr);		//释放动态开辟的数组空间
	L->arr = NULL;		//指针指向空
	L->size = 0;		//数据个数置为0
	L->capacity = 0;	//空间容量置为0
	return 1;
}

/***
*	函数名称:void CheckCapacity(SeqList* L) 
*	函数功能:判断顺序表是否已满,若容量已满则进行2倍扩容
*	入口参数:SeqList* L
*	出口参数:none
*	返回类型:void
***/
void CheckCapacity(SeqList* L) 
{
	assert(L != NULL);			//assert() 断言 值为假(0)时终止程序执行
	//判断容量是否已满
	if(L->size == L->capacity){
		size_t newcapacity;		//新容量
		//判断现有容量是否为0
		if (L->capacity == 0)
			newcapacity = L->capacity = 4;	//设置默认容量为4
		else
			newcapacity = L->capacity * 2;	//将现有容量的2倍大小存入newcapacity中
		//realloc(void *__ptr, size_t __size):更改已经配置的内存空间,即更改由malloc()函数分配的内存空间的大小。
		//将L->arr扩容至newcapacity大小后赋给新的指针p
		ElemType* p = (ElemType*)realloc(L->arr, newcapacity * sizeof(ElemType));
		//判断空间是否开辟失败,失败则返回错误 结束程序
		if (p == NULL) {
			perror("realloc");
			exit(-1);
		}
		else {
			//空间开辟成功
			L->arr = p;		//扩容空间p赋值给L->arr
			L->capacity = newcapacity; //更新容量
		}
	}
}

/***
*	函数名称:int SeqListPushBack(SeqList* L, ElemType x)
*	函数功能:从顺序表尾部插入一个元素x
*	入口参数:SeqList* L, ElemType x
*	出口参数:1
*	返回类型:int
***/
int SeqListPushBack(SeqList* L, ElemType x) {
	assert(L != NULL);		//断言 顺序表L存在
	CheckCapacity(L);		//检查顺序表是否已满,已满则扩容
	L->arr[L->size] = x;	//尾部插入数据x
	L->size++;				//有效数据个数+1
	return 1;
}

/***
*	函数名称:int SeqListPopBack(SeqList* L)
*	函数功能:从顺序表尾部删除一个元素
*	入口参数:SeqList* L
*	出口参数:1
*	返回类型:int
***/
int SeqListPopBack(SeqList* L) {
	assert(L != NULL);		//L必须存在
	assert(L->size > 0);	//顺序表不能为空
	L->size--;	//数据有效个数-1
	return 1;
}

/***
*	函数名称:int SeqListPushFront(SeqList* L, ElemType x)
*	函数功能:从顺序表头部插入一个元素x
*	入口参数:SeqList* L, ElemType x
*	出口参数:1
*	返回类型:int
***/
int SeqListPushFront(SeqList* L, ElemType x) {
	assert(L != NULL);		//断言 顺序表L存在
	CheckCapacity(L);		//检查顺序表是否已满,已满则扩容
	//将顺序表整体后移一位,空出第一个的位置
	for (size_t i = L->size; i > 0; i--)
	{
		L->arr[i] = L->arr[i - 1];
	}
	L->arr[0] = x;			//尾部插入数据x
	L->size++;				//有效数据个数+1
	return 1;
	
}

/***
*	函数名称:int SeqListPopFront(SeqList* L)
*	函数功能:从顺序表头部删除一个元素
*	入口参数:SeqList* L
*	出口参数:1
*	返回类型:int
***/
int SeqListPopFront(SeqList* L) {
	assert(L != NULL);		//L必须存在
	assert(L->size > 0);	//顺序表不能为空
	//顺序表整体前移,用后一个覆盖前一个
	for (size_t i = 0; i < L->size; i++)
	{
		L->arr[i] = L->arr[i + 1];
	}
	//顺序表长度-1
	L->size--;
	return 1;
}

/***
*	函数名称:int SeqListPrint(SeqList* L)
*	函数功能:打印出顺序表的内容
*	入口参数:SeqList* L
*	出口参数:1
*	返回类型:int
***/
int SeqListPrint(SeqList* L) {
	assert(L != NULL);
	if (L->size == 0) return 0;
	for (size_t i = 0; i < L->size; i++)
	{
		printf("%d ", L->arr[i]);
	}
	return 1;
}

/***
*	函数名称:int SeqListFind(SeqList* L, ElemType x)
*	函数功能:在顺序表中查找元素x的值,返回下标i
*	入口参数:(SeqList* L, ElemType x
*	出口参数:i|-1
*	返回类型:int
***/
int SeqListFind(SeqList* L, ElemType x) {
	assert(L != NULL);
	for (int i = 0; i < L->size; i++)
	{
		//查找到改元素, 返回该元素的下标
		if (L->arr[i] == x) {
			
			return i;
		}
	}
	return -1;	//找不到返回-1
}

/***
*	函数名称:int SeqListInsert(SeqList* L, size_t i, ElemType x)
*	函数功能:在顺序表指定下标i的位置插入元素x
*	入口参数:SeqList* L, size_t i, ElemType x
*	出口参数:1
*	返回类型:int
***/
int SeqListInsert(SeqList* L, size_t i, ElemType x) {
	assert(L != NULL);
	assert(i >= 0 && i<=L->size);
	CheckCapacity(L);
	//将顺序表第i个元素整体往后位移,空出第i个元素的位置
	for (size_t j = L->size; j > i; j--)
	{
		L->arr[j] = L->arr[j - 1];
	}
	L->arr[i] = x;		//将x插入到i的位置
	L->size++;			//顺序表长度+1
	return 1;
}

/***
*	函数名称:int SeqListErase(SeqList* L, size_t i)
*	函数功能:删除顺序表的第i个元素
*	入口参数:SeqList* L, size_t i
*	出口参数:1
*	返回类型:int
***/
int SeqListErase(SeqList* L, size_t i) {
	assert(L != NULL);
	assert(L->size > 0);
	assert(i >= 0 && i < L->size);
	//将顺序表从第i个元素开始整体前移一位,覆盖前面的元素
	for (size_t j = i; j < L->size; j++)
	{
		L->arr[j] = L->arr[j + 1];
	}
	//元素个数-1
	L->size--;
	return 1;
}

/***
*	函数名称:size_t SeqListSize(SeqList* L)
*	函数功能:返回数据表中元素的个数
*	入口参数:SeqList* L, size_t i
*	出口参数:L->size
*	返回类型:size_t
***/
size_t SeqListSize(SeqList* L) {
	assert(L != NULL);
	return L->size;
}

/***
*	函数名称:int SeqListAt(SeqList* L, size_t i, ElemType x)
*	函数功能:修改指定下标i位置的元素的值为x
*	入口参数:SeqList* L, size_t i, ElemType x
*	出口参数:1
*	返回类型:int
***/
int SeqListAt(SeqList* L, size_t i, ElemType x) {
	assert(L != NULL);
	assert(L->size > 0);
	assert(i >= 0 && i <= L->size);
	L->arr[i] = x;
	return 1;
}

int main() {
	int n,x,i;
	SeqList* L;
	L = SeqListInit();
	while (1) {
		printf("----------------------------------------------------------------------------------------\n");
		printf("********1.显示顺序表的值			2.插入一个元素到顺序表的尾部***\n");
		printf("********3.插入一个元素到顺序表的头部		4.从顺序表的尾部删除一个元素***\n");
		printf("********5.从顺序表的头部删除一个元素		6.查找元素x在顺序表中的位置****\n");
		printf("********7.在顺序表指定的位置插入元素		8.删除(释放)顺序表***********\n");
		printf("********9.在顺序表中删除指定下标位置的数据	10.修改指定下标位置的数据******\n");
		printf("********11.返回顺序表的元素个数			12.退出程序********************\n");
		printf("请输入选项:");
		scanf("%d", &n);
		if (n == 15) break;
		switch (n)
		{
		case 1:
			if (SeqListPrint(L))
				printf("\n顺序表的值打印成功!\n");
			else
				printf("\n顺序表的值打印失败!\n");
			break;
		case 2:
			printf("请输入要插入的元素:");
			scanf("%d", &x);
			if (SeqListPushBack(L, x))
				printf("元素%d插入成功!\n",x);
			else
				printf("元素%d插入失败!\n",x);
			break;
		case 3:
			printf("请输入要插入的元素:");
			scanf("%d", &x);
			if (SeqListPushFront(L,x))
				printf("元素%d插入成功!\n", x);
			else
				printf("元素%d插入失败!\n", x);
			break;
		case 4:
			if (SeqListPopBack(L))
				printf("成功从尾部删除一个元素!\n");
			else
				printf("从尾部删除一个元素失败!\n");
			break;
		case 5:
			if (SeqListPopFront(L))
				printf("成功从头部删除一个元素!\n");
			else
				printf("从头部删除一个元素失败!\n");
			break;
		case 6:
			printf("请输入要查找的元素:");
			scanf("%d", &x);
			if ((i = SeqListFind(L, x)) != -1)
				printf("元素%d在顺序表中的下标是%d\n", x,i);
			else
				printf("元素%d不在顺序表中\n",x);
			break;
		case 7:
			printf("请输入要插入的位置和插入的值(1 2):");
			scanf("%d %d", &i, &x);
			if (SeqListInsert(L, i, x))
				printf("元素%d插入位置%d成功\n",x,i);
			else
				printf("元素%d插入位置%d失败\n", x, i);
			break;
		case 8:
			if(SeqListDestory(L))
				printf("释放顺序表成功!\n");
			else
				printf("顺序表释放失败!\n");
			break;
		case 9:
			printf("请输入要删除元素的位置:");
			scanf("%d", &i);
			if (SeqListErase(L, i))
				printf("位置%d的元素删除成功!\n",i);
			else
				printf("位置%d的元素删除失败!\n",i);
			break;
		case 10:
			printf("请输入要修改的位置和修改的值(1 2):");
			scanf("%d %d", &i, &x);
			if (SeqListAt(L, i, x))
				printf("位置%d的元素成功修改为%d\n", i, x);
			else
				printf("修改失败\n");
			break;
		case 11:
			printf("顺序表的元素个数为%d个\n", SeqListSize(L));
			break;
		default:
			break;
		}
	}
	return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
线性表是一种常见的数据结构,它表示具有相同数据类型的一组元素的有序序列。线性表中的元素之间存在一种顺序关系,每个元素都有一个前驱和一个后继(除了第一个元素没有前驱,最后一个元素没有后继)。线性表可以用顺序存储结构或链式存储结构实现。 在顺序存储结构中,线性表的元素按照顺序存储在连续的内存空间中,可以通过元素的下标来访问和操作元素。插入或删除元素时,需要移动其他元素,因此操作的时间复杂度较高。 链式存储结构中,线性表的每个元素都包含一个数据域和一个指针域,指针指向下一个元素。通过指针的链接,元素可以按照任意顺序存储在内存中,插入和删除操作只需要改变指针的指向,因此时间复杂度较低。 线性表常见的操作包括插入、删除、查找、获取长度等。其中插入和删除操作需要注意保持线性表的顺序关系。 常见的线性表有数组、链表、栈和队列。数组是最简单的线性表,通过下标可以直接访问元素;链表是动态存储结构,插入和删除操作方便,但访问元素需要遍历链表;栈是一种特殊的线性表,只允许在表的一端进行插入和删除操作;队列也是一种特殊的线性表,只允许在表的一端进行插入操作,在另一端进行删除操作。这些数据结构在实际应用中都有各自的应用场景和优缺点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孑然R

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值