顺序表及其应用

1. 顺序表概念及结构

1.1 线性表

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

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

2. 顺序表分类

2.1 顺序表和数组的区别

顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。

2.2 顺序表分类

2.2.1 静态顺序表(使用定长数组存储元素)

Typedef int SLDataType;是将整型int命名为SLDataType,要知道数据表可不一定只存储整型数据啊,当我们需要更改数据类型时,只需要把Int改变一下就行了,VS2022上虽然有一键替换功能,但最好不用,因为不可控元素太多,容易使程序产生意想不到的结果 。

#define N 6中的define 定义宏,简单来说就是把N替代6再输入N时即代表为6。

剩下的结构体包含了整个静态表插入的数据及有效数据个数。

缺陷: 

由于这种顺序表不可动态申容,故容量从一开始就规定好了容量,就会导致空间给少了不够用,给多了照成空间浪费。

2.2.2 动态顺序表(按需申请)

动态顺序表中结构体定义了有效数据个数和空间容量。

相较就静态顺序表而言,动态顺序表空间利用率更高,但仍有浪费。

故而我们主要来实现一下动态顺序表。

3. 动态顺序表的实现

动态顺序表所需头文件如下,从代码中我们不难看出顺序表的功能,有增删查改等功能。

1.  #pragma once
2.  include<stdio.h>
3.  #include<stdlib.h>
4.  #include<assert.h>
5.  //定义顺序表的结构
6.  
7.  
8.  #define N 100
9.  //静态顺序表
10.  struct SeqList
11.  {
12.  	int arr[N];
13.  	int size;//有效数据个数
14.  };
15.  
16.    
17.  typedef int SLDataType;
18.  //动态顺序表
19.  typedef struct SeqList//sequence:顺序的;List:列表  仅是个名字,无特殊含义
20.  {
21.  	SLDataType* arr;
22.  	int size;//有效数据个数
23.  	int capacity;//空间大小
24.  }SL;
25.  
26.  typedef struct SeqList SeqList;
27.  SeqList s1;
28.  顺序表初始化
29.  void SLINit(SL* ps);
30.  //顺序表的销毁
31.  void SLDestroy(SL* ps);
32.  void SLPrint(SL s);//由于并不改变顺序表中内容,所以可以不用传指针(用于查看顺序表中功能是否可以正常使用)
33.  //头部插入 / 尾部插入
34.  void SLPushBack(SL* ps, SLDataType);
35.  void SLPushFront(SL* ps, SLDataType);
36.  //头部删除/尾部删除
37.  void SLPopback(SL* ps);
38.  void SLPopFront(SL* ps);
39.  //指定位置之前插入/删除数据
40.  void SLInsert(SL* ps, int pos, SLDataType x);
41.  void SLErace(SL* ps, int pos);
42.  int SLFind(SL* ps, SLDataType x);

3.1 顺序表初始化

1. //顺序表初始化
2. void SLInit(SL* ps)
3. {
4. 	 assert(ps);
5. 	 ps->arr = NULL;
6. 	 ps->size = ps->capacity = 0;
7. }

3.2 顺序表的销毁 

1.  //顺序表的销毁
2.  void SLDestroy(SL* ps)
3.  {
4. 	   if (ps->arr)
5. 	   {
6. 	 	  free(ps->arr);
7.     }
8.     ps->arr = NULL;
9. 	   ps->size = ps->capacity = 0;
10.  }

3.3 顺序表的打印

1. void SLPrint(SL s)
2. {
3.  	for (int i = 0; i < s.size; i++)
4.  	{
5.  		printf("%d ", s.arr[i]);
6.  	}
7.  	printf("\n");
8. }

3.4 顺序表的尾部/头部插入

1. //检查容量并扩容
2.  void SLCheckCapacity(SL* ps)
3.  {
4.  	assert(ps);
5.  	if (ps->capacity == ps->size)
6.  	{
7.  		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
8.  		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * 
 sizeof(SLDataType));
9.  		if (tmp == NULL)
10.  		{
11. 			perror("realloc fail!");
12. 			exit(1);
13. 		}
14. 		ps->arr = tmp;
15. 		ps->capacity = newcapacity;
16. 	}
17. }
18. //尾插
19. void SLPushBack(SL* ps, SLDataType x)
20. {
21. 	assert(ps);
22. 	SLCheckCapacity(ps);
23. 	ps->arr[ps->size++] = x;
24. }
25. //头插
26. void SLPushFront(SL* ps, SLDataType x)
27. {
28. 	assert(ps);
29. 	SLCheckCapacity(ps);
30. 	for (int i = ps->size; i > 0; i--)
31. 	{
32. 		ps->arr[i] = ps->arr[i - 1];
33. 	}
34. 	ps->arr[0] = x;
35. 	ps->size++;
36. }

3.5 顺序表的尾部/头部删除

1.  void SLPopBack(SL* ps)
2.  {
3.  	assert(ps && ps->size);
4.  	--ps->size;
5.  }
6.  void SLPopFront(SL* ps)
7.  {
8.  	assert(ps && ps->size);
9.  	for (int i = 0; i < ps->size; i++)
10. 	{
11. 		ps->arr[i] = ps->arr[i + 1];
12. 	}
13. 	ps->size--;
14. }

3.6 顺序表在任意位置插入数据

1.  void SLInsert(SL* ps, int pos, SLDataType x)
2.  {
3.  	assert(ps);
4.  	SLCheckCapacity(ps);
5.  	assert(pos >= 0 && pos <= ps->size);
6.  	for (int i = ps->size;i>pos;i--)
7.  	{
8.  		ps->arr[i] = ps->arr[i-1];
9.  	}
10. 	ps->arr[pos] = x;
11. 	ps->size++;
12. }

3.7 顺序表删除任意位置的数据

1.  void SLInsert(SL* ps, int pos, SLDataType x)
2.  {
3.  	assert(ps);
4.  	SLCheckCapacity(ps);
5.  	assert(pos >= 0 && pos <= ps->size);
6.  	for (int i = ps->size;i>pos;i--)
7.  	{
8.  		ps->arr[i] = ps->arr[i-1];
9.  	}
10. 	ps->arr[pos] = x;
11. 	ps->size++;
12. }

3.8 顺序表中数据的查找

1.  int SLFind(SL* ps, SLDataType x)
2.  {
3.  	assert(ps);
4.  	for (int i = 0; i < ps->size; i++)
5.  	{
6.  		if (ps->arr[i] == x)
7.  		{
8.  			return i;
9.  		}
10. 	}
11. 	return -1;
12. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值