数据结构之——线性表与顺序表

本文详细介绍了线性表的定义,特别是重点讲解了顺序表的实现,包括静态存储和动态存储两种方式,并提供了完整的C语言接口实现,如初始化、销毁、打印、增容、插入、删除等操作。此外,还展示了各种操作的测试代码,便于理解顺序表的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、线性表的定义

 二、顺序表的实现

1. 顺序表的概念及结构

(1)顺序表的静态存储

(2)顺序表的动态存储

2. 顺序表的接口实现

(1)顺序表初始化

(2)顺序表销毁

(3)顺序表打印

(4)检查空间,如果满了,进行增容

(5)顺序表尾插

(6)顺序表尾删

(7)顺序表头插

(8)顺序表头删

(9)顺序表查找

(10)顺序表在pos位置插入x

(11)顺序表删除pos位置的值

(12)顺序表修改 

3. 测试代码


一、线性表的定义

        线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

        线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

  数组形式:

 链式结构:

 二、顺序表的实现

1. 顺序表的概念及结构

        顺序表是用一段 物理地址连续的存储单元 依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改
顺序表一般可以分为:
        1. 静态顺序表:使用定长数组存储。
        2. 动态顺序表:使用动态开辟的数组存储。

(1)顺序表的静态存储

// 顺序表的静态存储
#define N 100
typedef int SLDataType;
typedef struct SeqList
{
     SLDataType a[N]; // 定长数组
     int size;     // 有效数据的个数 
}SL;

(2)顺序表的动态存储

// 顺序表的动态存储
typedef struct SeqList
{
     SLDataType* a;  // 指向动态开辟的数组
     int size ;       // 有效数据个数
     int capicity ;   // 容量空间的大小
}SL;

2. 顺序表的接口实现

         静态顺序表有一个缺点,它只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表,完成数据的增删查改

(1)顺序表初始化

       
//顺序表初始化
void SeqListInit(SL* ps)
{
	ps->a = NULL;   //初始顺序表为空
	ps->size = ps->capacity = 0;   //初始数据个数与初始空间容量为0
}

(2)顺序表销毁

//顺序表销毁
void SeqlistDestroy(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

(3)顺序表打印

//顺序表打印
void SeqListPrint(SL* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d  ", ps->a[i]);
	}
    printf("\n");
}

(4)检查空间,如果满了,进行增容

//检查空间,如果满了,进行增容
void SeqListCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; 
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity); 
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

(5)顺序表尾插

//顺序表尾插
void SeqListPushBack(SL* ps, SLDataType x)
{
	SeqListCheckCapacity(ps); //检查空间容量是否足够,不够扩容
	ps->a[ps->size] = x;
	ps->size++;
}

测试结果:

(6)顺序表尾删

//顺序表尾删
void SeqListPopBack(SL* ps)
{
	if (ps->size > 0)  // assert(ps->size >0 )
		ps->size--;
}

测试结果:

(7)顺序表头插

        从后往前(end=size-1),依次挪动数据到下一个位置(end--),当end<0时停止,挪动完成后,在0处插值,size++。

//顺序表头插
void SeqListPushFront(SL* ps, SLDataType x)
{
	SeqListCheckCapacity(ps);
    //挪动数据
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[0] = x;
	ps->size++;
}

测试结果:

(8)顺序表头删

        从前往后(begin=1),依次挪动数据到前一个位置(begin++),当begin=size时停止,最后再size--。

//顺序表头删
void SeqListPopFront(SL* ps)
{
	assert(ps->size > 0);  ////断言,不满足条件会报错
	int begin = 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

测试结果:

(9)顺序表查找

//顺序表查找
//找到了返回x的下标位置,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x)
{
	for(int i=0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
			return i;
	}
	return -1;
}

测试结果:

(10)顺序表在pos位置插入x

        与顺序表的头插同理从后往前(end=size-1),依次挪动数据到下一个位置(end--),当end<pos时停止,挪动完成后,在pos处插值,size++。

//顺序表在pos位置插入x
int SeqListInsert(SL* ps, int pos, SLDataType x)
{
	assert(pos >= 0 && pos <= ps->size);   //断言,不满足条件会报错
	SeqListCheckCapacity(ps);
	int end = ps->size-1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}
	ps->a[pos] = x;
	ps->size++;
}

测试结果:

(11)顺序表删除pos位置的值

        与顺序表的头删同理从前往后(begin=pos+1),依次挪动数据到前一个位置(begin++),当begin=size时停止,最后再size--。

//顺序表删除pos位置的值
int SeqListErase(SL* ps, int pos)
{
	assert(pos >= 0 && pos <= ps->size);   //断言,不满足条件会报错
	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

测试结果:

(12)顺序表修改 

//顺序表修改
void SeqListModify(SL* ps, int pos, SLDataType x)
{
	assert(pos >= 0 && pos <= ps->size);  //断言,不满足条件会报错
	ps->a[pos] = x;
}

3. 测试代码

void test1(void)
{
	SL ps;  //结构体变量
	SeqListInit(&ps);  //顺序表初始化
	//尾插
	printf("尾插: ");
	SeqListPushBack(&ps, 1);
	SeqListPushBack(&ps, 2);
	SeqListPushBack(&ps, 3);
	SeqListPushBack(&ps, 4);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");

	//尾删
	printf("尾删:");
	SeqListPopBack(&ps);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");

	//头插
	printf("头插: ");
	SeqListPushFront(&ps, 6);
	SeqListPushFront(&ps, 7);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");

	//头删
	printf("头删: ");
	SeqListPopFront(&ps);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");
}

void test2(void)
{
	SL ps;  //结构体变量
	SeqListInit(&ps);  //顺序表初始化
	//尾插
	printf("尾插: ");
	SeqListPushBack(&ps, 1);
	SeqListPushBack(&ps, 2);
	SeqListPushBack(&ps, 3);
	SeqListPushBack(&ps, 4);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");

	//查找
	int rst = SeqListFind(&ps, 3);
	printf("3的位置是:%d\n", rst);
	rst = SeqListFind(&ps, 6);
	printf("6的位置是:%d\n", rst);
	printf("\n");
}

void test3() {
	SL ps;  //结构体变量
	SeqListInit(&ps);  //顺序表初始化
	//尾插
	printf("尾插: ");
	SeqListPushBack(&ps, 1);
	SeqListPushBack(&ps, 2);
	SeqListPushBack(&ps, 3);
	SeqListPushBack(&ps, 4);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");

	//在位置2处增加9
	printf("在位置2处增加9: ");
	SeqListInsert(&ps, 2, 9);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");
}

void test4() {
	SL ps;  //结构体变量
	SeqListInit(&ps);  //顺序表初始化
	//尾插
	printf("尾插: ");
	SeqListPushBack(&ps, 1);
	SeqListPushBack(&ps, 2);
	SeqListPushBack(&ps, 3);
	SeqListPushBack(&ps, 4);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");

	//删除位置1的值
	printf("删除位置1的值: ");
	SeqListErase(&ps, 1);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");
    
    //修改
	printf("将位置2的值改为20: ");
	SeqListModify(&ps, 2, 20);
	SeqListPrint(&ps); // 顺序表打印
	printf("\n");
}

int main()
{
	test1();
//	test2();
//	test3();
//	test4();
	return 0;
}

当你足够努力,幸运总会与你不期而遇!!!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值