线性表——顺序表 《完整顺序表的接口实现(数据结构)》

双向链表的实现代码及接口https://blog.csdn.net/dpfxaca6/article/details/89490360
单向链表的实现代码及接口https://blog.csdn.net/dpfxaca6/article/details/89472595

首先我们先介绍一下线性表,线性表是N个有着相同特性的数据元素的有限链表。线性表是一种实际中广泛使用的数据结构,常见的线性结构有:顺序表,链表,栈,队列,字符串…。

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

在这里插入图片描述
顺序表

顺序表的概念:它是一段物理地址连续的储存空间依次储存数据元素的线性结构,一般情况下,使用的是数组储存,在数组中,完成数据的增删查改。

首先,先给大家一些接口,如果能力强的同学,可以自己练习一下。

#ifndef   __SEQLIST_H__
#define   __SEQLIST_H__

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<assert.h>

//顺序表的静态储存;
//#define N 100;     //这一部分,我们太不需要,因为动态符合我们所需要的。
//typedef  int  SLDataType;
//
//typedef struct SeqList
//{
//     SLDataType array[N];
//	 size_t  size;
//}SeqList;


//顺序表的动态储存;
typedef int SLDataType;

typedef struct SeqList
{
    SLDataType* _array;
	size_t _size;
	size_t _capacity; 
}SeqList;


void SeqListInit(SeqList* ps,size_t _capacity);
void SeqListDestory(SeqList* ps);
void CheckCapacity(SeqList* ps);
void SeqListPushBank(SeqList* ps,SLDataType x);
void SeqListPopBank(SeqList* ps);
void SeqListPushFort(SeqList* ps,SLDataType x);
void SeqListPopFort(SeqList* ps);
void SeqListPrint(SeqList* ps);

int SeqListFind(SeqList* ps, SLDataType x);
void SeqListInsert(SeqList* ps ,size_t pos , SLDataType x);
void SeqListErase(SeqList* ps, size_t pos);

void SeqListBubblesort(SeqList* ps, SLDataType x);
int SeqListBinaryFind(SeqList* ps, SLDataType x);
void SeqListRemoveAll(SeqList* ps, SLDataType x);



#endif   //__SEQLIST_H__

下来就是我们的完整代码了,根据上面的接口,我们测试函数与主函数放在一起了,如果需要分开的话,请自行把分开。

#include "SeqList.h"

void SeqListInit(SeqList* ps,size_t capacity) //初始化
{
    assert(ps);
	ps->_array = (SLDataType*)malloc(sizeof(SLDataType)*capacity);
	ps->_capacity = capacity;
	ps->_size = 0;
}
void SeqListDestory(SeqList* ps) //释放
{
    assert(ps);
	if(ps->_array)
	{
	    free(ps->_array );
		ps->_array  = NULL;
		ps->_capacity = ps->_size = 0;
	}
}
void CheckCapacity(SeqList* ps)  //检查容量
{
    assert(ps);
	if(ps->_size == ps->_capacity )  //等号没有写好;
	{
		ps->_capacity *= 2;
		ps->_array =realloc(ps->_array , ps->_capacity * sizeof(SLDataType));
		assert(ps->_array); 
	}
}
void SeqListPushBank(SeqList* ps,SLDataType x)  //尾插
{
     assert(ps);
     CheckCapacity(ps);
	 ps->_array[ps->_size ] = x;
	 ps->_size++;
}
void SeqListPopBank(SeqList* ps) //尾删
{
     assert(ps && ps->_array);
	 ps->_size--;
}
void SeqListPushFort(SeqList* ps,SLDataType x) //头插
{
	int end = ps->_size-1;
      assert(ps);
	  CheckCapacity(ps);
	  while(end >= 0)
	  {
	      ps->_array[end+1] = ps->_array[end];
		 --end;
	  }
	  ps->_array[0]= x;
	  ps->_size++;

}
void SeqListPopFort(SeqList* ps)  //头删
{
   int left = 0;
   int right = ps->_size - 1;
   assert(ps);
   while(left < right)
   {
       ps->_array[left] = ps->_array[left + 1];
	   left++;
   }
   ps->_size--;
}


int SeqListFind(SeqList* ps, SLDataType x)  //查找
{
	int i = 0;
    assert(ps);
	for(i = 0; i< ps->_size;i++)
	{
	    if(x == ps->_array[i])
		{
			return i;
		}
	}
	return -1;
}
void SeqListInsert(SeqList* ps ,size_t pos , SLDataType x) //在当前位置插入
{
	int end = ps->_size -1;
    assert(ps && pos < ps->_size );
    while(end >= 0)  
	{
	    ps->_array[end + 1] = ps->_array[end];
		--end;
	}
	ps->_array[pos] = x;
	ps->_size++;
	
    
}
void SeqListErase(SeqList* ps, size_t pos)    //在当前位置删除
{
	int i = 0;
   assert(ps);
   while(pos < ps->_size)    //这里不是变量加一,而是找的那个位置加一;
   {
		ps->_array[pos] = ps->_array[pos + 1];
		pos++;
   }
  ps->_size--;
}

void SeqListBubblesort(SeqList* ps)   //冒泡排序
{
	int i = 0 ;
	int end = 0;
	end = ps->_size-1 ;
   assert(ps);
   while(end >= 0)
   {
       for(i = 0 ;i < end ; i++)
	   {
	        if(ps->_array[i] > ps->_array[i + 1])
			{
			   SLDataType tmp = ps->_array[i];
			   ps->_array[i] = ps->_array[i + 1];
			   ps->_array[i+1] = tmp;
			}
	   }
	   end--;
   }
   
}
int SeqListBinaryFind(SeqList* ps, SLDataType x) //二分查找(有一点小问题,找到了,请告诉我)
{
    int start = 0;
	int end = ps ->_size;
	int mid = 0;
	while(start < end)
	{
		mid = (start + end)/2;
		if(ps ->_array[mid] == x)
		{
			return mid;
		}
		else if(ps ->_array[mid] > x)
		{
			end = mid + 1;
		}
		else
		{
			start = mid + 1;
		}
	}
	return -1;
	
}
void SeqListRemoveAll(SeqList* ps, SLDataType x) //删除当前以后的全部位置
{
	int i =0 ;
     assert(ps);
     for(i =0 ; i< ps->_size ;i++)
	 {
	    if(ps->_array[i] == x)
		{
		    SeqListErase(ps,x);
			i--;
		}
	 }
}
void SeqListPrint(SeqList* ps)
{
	 int i = 0;
     for(i  = 0; i < ps->_size ; i++)
	 {
	       printf("%d ",ps->_array[i]);
	 }
	 printf("\n");
}


int main()
{
   SeqList s;
   SeqListInit(&s,10);
   SeqListPushBank(&s,1);
   SeqListPushBank(&s,3);
   SeqListPushBank(&s,2);
   SeqListPushBank(&s,4);
   SeqListPushBank(&s,6);
   SeqListPushBank(&s,8);
   SeqListPushBank(&s,7);
   SeqListPrint(&s);
//几个函数接口的实现,调用函数。
   SeqListBubblesort(&s);
   SeqListPrint(&s);

   //printf("%d\n",SeqListBinaryFind(&s,7));

   SeqListRemoveAll(&s,4);
      SeqListPrint(&s);


   //前几个接口的实现,调用函数。
   /*SeqListPopBank(&s);
   SeqListPrint(&s);
   
   SeqListPushFort(&s,0);
   SeqListPrint(&s);

   SeqListPopFort(&s);
   SeqListPrint(&s);*/
    
   /* printf("%d\n",SeqListFind(&s,2));

   SeqListInsert(&s , 0 , 0);
   SeqListPrint(&s);

   SeqListErase(&s,0);
   SeqListPrint(&s);*/



   SeqListDestory(&s);
   return 0;
}

顺序表的问题及思考
问题:
1. 中间/头部的插入删除,时间复杂度为O(N)
2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,
我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

思考:

如何解决以上问题呢?下面给出了链表的结构来看看。我会把链接发在下面的

双向链表的实现代码及接口:https://blog.csdn.net/dpfxaca6/article/details/89490360
单向链表的实现代码及接口:https://blog.csdn.net/dpfxaca6/article/details/89472595

如果还有什么地方,不足的话,请大佬下面留言,谢谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值