数据结构—C语言实现顺序表(头插、尾插、头删、尾删)

初始化

初始化函数命名:SeqListInit
解释一下为什么叫这个名字:
Seq->顺序,List->表,Init->初始化。
这些字母都是对应的单词的首字母,方便看懂。

初始化就是给一个顺序表赋值,只不过是赋值为0。这就好像你定义一个变量随手就写出(int a=0;)一样。
顺序表的本质是一个结构体,里面有多个不同的成员,这些成员分别是:a->一个数组(你也可以理解为一个指针),size->记录顺序表里有多少个元素,也叫计数,capacit->顺序表有多大空间。
我们把指针初始化成NULL,其他两个初始化成0。

void SeqListInit(SL* ps)
 	{
 		ps->a = NULL;
 		ps->size = ps->capacity = 0;
 	}

检查容量

初始化函数命名:SeqListCheckCapacity
解释一下为什么叫这个名字:
Seq->顺序,List->表,Check->检查,Capacity->容量。
这些字母都是对应的单词的首字母,方便看懂。

这个函数的作用是:给顺序表增加数字的时候检查是否有空间放新的数字,如果没有空间,就扩容(扩大容量),让新的数字有地方插入。

void SeqListCheckCapacity(SL* ps)
 59	{
 60		//容量被占满或者刚开始啥也没有
 61		if (ps->capacity == ps->size)
 62		{
 63			//如果刚开始容量是0,那么就开辟4个字节的空间
 64			//如果容量不是0,那么就扩容到原来的两倍
 65			int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
 66			SeqListDataType* tmp = (SeqListDataType*)realloc(ps->a, newcapacity * sizeof(SeqListDataType));
 67			//如果开辟失败
 68			if (tmp == NULL)
 69			{
 70				printf("增容失败 \n");
 71				exit(-1);
 72			}
 73			//扩容成功
 74			ps->a = tmp;
 75			ps->capacity = newcapacity;
 76		}
 77	}

头插法

头插法函数命名:SeqListPushFront
解释一下为什么叫这个名字:
Push->推,这里你可以理解成把一个数推进顺序表里,也就是插入顺序表了。Front->头,从头开始。

假设有一组数{1,2,3,4}现在要在1的前面插入0,这就是头插法。
首先我们要检查顺序表是否有足够的空间,需要调用【检查容量】函数,这个函数我在前面的已经讲过了,忘记的朋友再上去看看。
为了在头插入一个数,我们的做法是把每个数字都往后移,这样就能在最前面空出一个位置放新的数字。
那么怎么把每个数字都往后移呢?
size是最后一个数组的下标,它能记录当前顺序表有多少个数字,因为数组的下标是从0开始的,所以size-1即可得到当前顺序表的元素个数。
得到元素个数就相当于来到了数组的最后位置,这时把元素的最后位置定义成end。把这个最后位置加1,就相当于这个最后位置向后移了一位。为了把每个元素都向后移动一位,我们需要重复这个过程,并且把end减1。
每个元素都移完之后,就可以把新数字x放在空出的位置(即a【0】),增加了一个新数,顺序表的计数size也要加1。

void SeqListPushFront(SL* ps, SeqListDataType x)
 15	{
 16		//先检查容量是否够用
 17		SeqListCheckCapacity(ps);
 18		int end = ps->size - 1;
 19		while (end>=0)
 20		{
 21			ps->a[end+1] = ps->a[end];
 22			end--;
 23		}
 24		ps->a[0] = x;
 25		ps->size++;
 26	
 27	}
 28	

尾插法

尾插法函数命名:SeqListPushBack
解释一下为什么叫这个名字:
Push->推,这里你可以理解成把一个数推进顺序表里,也就是插入顺序表了。Back->尾,从尾部开始。

假设有一组数{1,2,3,4}现在要在4的后面插入5,这就是尾插法。
同样的,在顺序表里增加一个新数之前要检查是否用足够的空间,需要调用【检查容量】函数。
尾插法是最简单的插入方法,在最后增加(size处)赋值要增加的x即可。
增加之后,把计数的size加1。

void SeqListPushBack(SL* ps, SeqListDataType x)
 30	{
 31		//先检查容量是否够用
 32		SeqListCheckCapacity(ps);
 33		ps->a[ps->size] = x;
 34		ps->size++;
 35	}
 36	

头删法

头删法函数命名:SeqListPopFront
解释一下为什么叫这个名字:
Pop->删除,Front->头,从头开始。

假设有一组数{1,2,3,4}现在要把1删掉,这就是头删法。
删除之前首先要判断顺序表里是否为空,如果顺序表为空就不能删了。assert是断言函数,如果数序表的计数大于0才会执行下面的代码,否则程序终止。
为了在头删除一个数,我们的做法是把每个数字都往前移,这样就能把最前面的数字删除了。
那么怎么把每个数字都往前移呢?
我们的目的是删掉第一个数,那么就要第二个数移到第一个数的位置,也就是从第二个数开始。第二个数的下标是1,所以begin是1。
为了把所有的数都往前移,我们需要循环这个过程。每移完一个数字,都要把begin加1,直到begin来到顺序表的最后(size处)。
循环结束之后,数字也就被删除了。之后把顺序表的计数size减1。

void SeqListPopFront(SL* ps)
 38	{
 39		assert(ps->size > 0);
 40		//为什么要begin=1?
 41		//从第二个开始往前移
 42		int begin = 1;
 43		while (begin < ps->size)
 44		{
 45			ps->a[begin-1] = ps->a[begin ];
 46			begin++;
 47		}
 48		ps->size--;
 49	}
 50	

尾删法

尾删法函数命名:SeqListPopBack
解释一下为什么叫这个名字:
Pop->删除,back->尾,从尾部开始。

假设有一组数{1,2,3,4}现在要把4删掉,这就是尾删法。
删除之前首先要判断顺序表里是否为空,如果顺序表为空就不能删了。assert是断言函数,如果数序表的计数大于0才会执行下面的代码,否则程序终止。
尾删只需要把计数减1即可。
你可以这么理解:把最后数字【4】比做一个人,他去银行取钱,银行是叫号排队取钱,现在把他的号撕毁,永远就叫不到这个人了。
顺序表也是同理,把计数减1,就是把这个数删掉了。

void SeqListPopBack(SL* ps)
 53	{
 54		assert(ps->size>0)55		ps->size--;
 56	}

打印函数

尾删法函数命名:SeqListPrint
解释一下为什么叫这个名字:
Print->打印,其他的没什么好解释的了。
通过循环打印每个数字。

void SeqListPrint(SL* ps)
 89	{
 90		int i = 0;
 91		for (i = 0; i < ps->size; i++)
 92		{
 93			printf("%d ", ps->a[i]);
 94		}
 95		printf("\n");
 96	}

释放空间

因为我们的空间全部是malloc出来的,不用了要把空间还给操作系统。不然会造成空间浪费。设置可能出现内存泄露的问题。

//释放空间函数
 80	void SeqListDestory(SL* ps)
 81	{
 82		free(ps->a);
 83		ps->a = NULL;
 84		ps->capacity=ps->size=0;
 85		
 86	}
 87	
  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值