数据结构之线性表的顺序存储结构(动态)

  1. 定义和特点都和静态类型的顺序表一样(详见上一篇文章),但是代码结构不太一样,初始化时不太一样,需要使用malloc或者是realloc申请内存,比起静态顺序表,动态的更加好调整顺序表的大小。
  2. 具体代码
    🥐1. 结构代码
    typedef int SeqDataType;
    #define OK 1
    #define ERROR 0
    typedef struct SeqList 
    { 
    	SeqDataType* a; 
    	int size; 
    	int capacity;
    }SeqList, SEQ;
    
    🥐2. 初始化顺序表
    void SeqListInit(SeqList* pq) 
    {
    	assert(pq); 
    	pq-> a = NULL; 
    	pq-> capacity = 0;
    	pq-> size = 0; 
    }
    
    🥐3. 检查是否要扩容
    思路讲解:
    👉判断顺序表空间是否满了,也就是判断是否需要增容就是要看pq->size == pq->capacity?增容:不增容。
    👉用条件运算符来确定增容后的新空间的大小,如果是仍未存储数据的新链表,则先让链表的
    容量为4
    (这个数值可以随便设置);如果已经存储了数据,但容量不够了,我们就让链表的空间每次增加一倍,也就是变成原来的两倍(可能有人会疑惑,为什么是两倍,其实这个也是为了减少数据的浪费,变成2倍比较保守)。
    👉在扩容时用realloc,当realloc的第一个参数为0时,其效果等同于malloc,用realloc可以完美实现最初开辟空间和增容的功能
    👉检查tmp是否为空,也就是检查是否成功开辟了新的空间,非空则把tmp赋值给pq->a,最后千万不要忘记更改capacity的值
    
    void SeqCheckCapacity(SeqList *pq)
    {
    	assert(pq);
    	if(pq->capacity == pq->size)
    	{
    		int newcapacity = (pq->capacity == 0 ? 4: pq->capacity * 2);
    		SeqDataType *tmp = (SeqDataType *)realloc(pq->a,sizeof(SeqDataType)*newcapacity);
    		if(tmp == NULL)
    		{
    			printf("ERROR\n");
    			return ERROR;
    		}
    		pq->a = tmp;
    		pq->capacity = newcapacity;
    	}
    }
    
    🥐4.顺序表尾插
    这里就需要注意在尾插前检查容量,并且不要忘记pq->size++。
    void SeqListPushBack(SeqList* pq, SeqDateType x)
    {
    	assert(pq);
    	
    	//检查空间大小
    	SeqCheckCapacity(pq);
    	pq->a[pq->size] = x;
    	pq->size++; 
    }
    
    🥐 5.顺序表头插
    需要将顺序表整体往后移动,空出头部一个位置给插入
    void SeqListPushFront(SeqList* pq, SeqDataType x)
    {
    	int i;
    	assert(pq);
    	SeqCheckCapacity(pq);
    	for(i=pq->size-1;i>=0;i--)
    	{
    		pq->a[i+1] = pq->a[i];
    	}
    	pq->a[0] = x;
    	pq->size++;
    }
    
    🥐6. 顺序表尾删
    直接将记录数组有效个数的变量size减减即可,这样就访问不到了
    ❗没必要对要删除的这个元素进行置空等等,因为不影响【因为当后面如果尾插的话,就会直接覆盖原来的数据了~】
    void SeqListPopBack(SeqList* pq)
    {
    	assert(pq);
    	if(pq->size == 0)
    		return;
    	pq->size--;
    }
    
    🥐7.顺序表头删
    需要将顺序表整体前移数据,覆盖第一位数据即达到删除的目的
    void SeqListPopFront(SeqList* pq)
    {
    	assert(pq);
    	int i;
    	if(pq->size == 0)
    		return;
    	for(i = 0;i<pq->size-1;i++)
    	{
    		pq->a[i] = pq->a[i+1];
    	}
    	pq->size--;
    }
    
    🥐8. 查找元素
    遍历顺序表一一比较查找是否有我们想要的元素。
    • 没有,则返回-1
    • 有,则返回元素的下标(若有多个符合要查找的元素,则返回优先找到的元素的下标)
    int SeqListFind(SeqList*pq, SeqDataType x)
    {
    	int i;
    	assert(pq);
    	for(i = 0;i<pq->size;i++)
    	{
    		if(x== pq->a[i])
    		{
    			return i;
    		}
    	}
    	return -1;
    }
    
    🥐9.修改元素
    直接访问想要修改的元素的下标进行修改
    💥特别注意: 修改元素的下标要在顺序表有效个数的范围内,修改第pos个元素,下标是pos-1
    void SeqListModify(SeqList*pq, int pos, SeqDataType x)
    {
    	//pos的取值在1<=pos<=pq->size
    	assert(pq);
    	if(pos < 1 || pos>pq->size)
    		return;
    	pq->a[pos-1] = x;
    }
    
    🥐10.任意位置前插入元素
    将从顺序表中要插入的位置开始,往后原有的元素整体往后移动,腾出空位来插入
    💥特别注意: 插入的位置要在顺序表有效个数的范围内
    void SeqListInsert(SeqList*pq, int pos, SeqDataType x)
    {
    	int i;
    	assert(pq);
    	if(pos < 1 || pos > pq->size+1)
    		return;
    	SeqCheckCapacity(pq);
    	for (i = pos->size;i>=pos;i--)
    	{
    		pq->a[i] = pq->a[i-1];
    	}
    	pq->a[pos- 1] = x;
    	pq->size++;
    }
    
    🥐11.任意位置删除元素
    将从顺序表中要删除的元素开始,往后所有的元素整体往前移动,后面的元素覆盖要删除的位置的元素,以达到删除的目的
    💥特别注意: 删除的位置要在顺序表有效个数的范围内
    void SeqListDelete(SeqList*pq, int pos)
    {
    	int i;
    	assert(pq);
    	if(pq->size == 0)
    		return;
    	if(pos < 1 || pos >pq->size)
    		return;
    	for (i = pos;i < pq->size;i++)
    	{
    		pq->a[i-1] = pq->a[i];
    	}
    	pq->size--;
    }
    
    🥐12.打印顺序表
    遍历顺序表一一打印即可
    void SeqListPrint(SeqList* pq)
    {
    	int i;
    	assert(pq);
    	for(i = 0;i< pq->size;i++)
    	{
    		printf("%d ",pq->a[i]);
    	}
    	printf("\n");
    }
    
    🥐13.销毁顺序表
    直接将顺序表中的成员变量置为0,且释放顺序表的空间即可
    void SeqListDestory(SeqList* pq)
    {
    	assert(pq);
    	free(pq->a); 
    	pq->a = NULL; 
    	pq->capacity = pq->size = 0;
    }
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值