数据结构---顺序表Sequence List(数组Array)

  • 简介

  • 特点:连续内存空间,元素通过索引访问。
  • 时间复杂度:访问元素为O(1),插入/删除元素平均为O(n)(需要移动元素)。
  • 应用场景:随机访问频繁,数据大小已知的情况。
  • 顺序表和普通数组的区别主要有以下两点:

  • 1.顺序表的长度可以动态增长,普通数组的长度是固定的。
    2.顺序表要求插入的数据在内存中是连续的,普通数组的数据存放可以不连续。

  • 实现顺序表

  • 创建SeqList.h,   
  •        SeqList.c,       
  •         test.c文件
  • 创建动态顺序表

  • ​
    //定义动态顺序表结构
    typedef int SLDatatype;
    
    typedef struct SeqList {
    	SLDatatype* arr;
    	int capacity; //空间大小
    	int size;     //有效数据个数
    }SL;
    
    ​//typedef struct SeqList SL;

  •           初始化

  • //初始化
    void SLInit(SL* ps);

  • //初始化
    void SLInit(SL* ps)
    {
    	ps->arr = NULL;
    	ps->size = ps->capacity = 0;
    }

  •           销毁

  • //销毁
    void SLDestroy(SL* ps);

  • void SLDestroy(SL* ps)
    {
    	if (ps->arr)//相当于ps->arr != NULL
    	{
    		free(ps->arr);
    	}
    	ps->arr = NULL;
    	ps->size = ps->capacity = 0;
    }

  •           打印

  • //打印
    void SLPrint(SL* ps);

  • void SLPrint(SL* ps)
    {
    	for (int i = 0; i < ps->size; i++)
    	{
    		printf("%d ", ps->arr[i]);
    	}
    	printf("\n");
    }

  •           扩容

  • void SLCheckCapacity(SL* ps)
    {
    	//判断空间是否充足
    	if (ps->size == ps->capacity)
    	{
    		//增容//0*2 = 0
    		//若capacity为0,给个默认值,否则×2倍
    		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
    		SLDatatype* tmp = (SLDatatype*)realloc(ps->arr, newCapacity * sizeof(SLDatatype));
    		if (tmp == NULL)
    		{
    			perror("realloc fail!");
    			exit(1);
    		}
    		ps->arr = tmp;
    		ps->capacity = newCapacity;
    	}

    插入

  •           尾插

  • ​
    //尾部插入数据
    void SLPushBack(SL* ps, SLDatatype x);
    
    ​

  • //尾部插入数据
    void SLPushBack(SL* ps, SLDatatype x)
    {
    	//粗暴的解决方法---断言
    	assert(ps);//等价于assert(ps != NULL)
    
    	温柔的解决方式
    	//if (ps == NULL)
    	//{
    	//	return;
    	//}
    	SLCheckCapacity(ps);
    	ps->arr[ps->size++] = x;
    }

  •           头插

  • //头部插入数据
    void SLPushFront(SL* ps, SLDatatype x);
    
    

  • //头部插入数据
    void SLPushFront(SL* ps, SLDatatype x)
    {
    	assert(ps);
    	//判断空间是否足够
    	SLCheckCapacity(ps);
    	
    	//数据整体后移一位
    	for (int i = ps->size; i > 0; i--)
    	{
    		ps->arr[i] = ps->arr[i - 1];
    	}
    	//下标为0的位置空出来
    	ps->arr[0] = x;
    
    	ps->size++;
    }
    

  • 在指定位置之前插入数据

  • //在指定位置之前插入数据
    void SLInsert(SL* ps, SLDatatype x, int pos);

  • //在指定位置之前插入数据(空间足够才能直接插入数据)
    void SLInsert(SL* ps, SLDatatype x, int pos)
    {
    	assert(ps);
    	assert(pos >= 0 && pos <= ps->size);
    
    	SLCheckCapacity(ps);
    
    	//pos及之后的数据整体向后移动一位
    	for (int i = ps->size; i > pos  ; i--)
    	{
    		ps->arr[i] = ps->arr[i - 1]; //pos+1   ->   pos
    	}
    	
    	ps->arr[pos] = x;
    	ps->size++;
    }

    删除

  •           尾删

  • ​
    //尾部删除
    void SLPopBack(SL* ps);
    
    ​

  • //尾部删除
    void SLPopBack(SL* ps)
    {
    	assert(ps);
    	assert(ps->size);
    
    	//ps->arr[ps->size - 1] = -1;//多余了
    	ps->size--;
    }
    

  •           头删

  • //头部删除
    void SLPopFront(SL* ps);
    

  • 头部删除
    void SLPopFront(SL* ps)
    {
    	assert(ps);
    	assert(ps->size);
    
    	//数据整体向前挪动一位
    	for ( int i = 0; i < ps->size - 1; i++)
    	{
    		ps->arr[i] = ps->arr[i + 1];//i = size-2
    	}
    	ps->size--;
    }

  • 删除指定位置的数据

  • //删除指定位置的数据
    void SLErase(SL* ps, int pos);
    

  • //删除指定位置的数据
    void SLErase(SL* ps, int pos)
    {
    	assert(ps);
    	assert(pos >= 0 && pos < ps->size);
    	//还有更多的限制:如顺序表不能为空....
    	
    	//pos之后的数据整体向前挪动一位
    	for (int i = pos; i < ps->size-1; i++)
    	{
    		ps->arr[i] = ps->arr[i + 1];// size-2 <- size-1
    	}
    	ps->size--;
    	
    }

    查找数据

    int SLFind(SL* ps, SLDatatype x)
    {
    	assert(ps);
    	for (int i = 0; i < ps->size; i++)
    	{
    		if (ps->arr[i] == x)
    		{
    			return i;
    		}
    	}
    	//没有找到:返回一个无效的下标
    	return -1;
    }


    测试

  • #include "SeqList.h"
    
    void SLtest01()
    {
    	SL s;
    	SLInit(&s);
    
    	//SLPushBack(&s, 1);
    	//SLPushBack(&s, 2);
    	//SLPushBack(&s, 3);
    	//SLPushBack(&s, 4);
    	//SLPushBack(&s, 5);
    	//SLPushBack(&s, 6);
    	//SLPushBack(NULL , 6);
    
    	//SLPushFront(&s, 1);
    	//SLPushFront(&s, 2);
    	//SLPushFront(&s, 3);
    	//SLPushFront(&s, 4);
    	//SLPrint(&s); //4 3 2 1
    
    	//SLPopBack(&s);
    	//SLPrint(&s);
    	//SLPopBack(&s);
    	//SLPrint(&s);
    	//SLPopBack(&s);
    	//SLPrint(&s);
    	//SLPopBack(&s);
    	//SLPrint(&s);
    	//SLPopBack(&s);
    	//SLPrint(&s);
    	//
    	//SLPopFront(&s);
    	//SLPrint(&s);
    	//SLPopFront(&s);
    	//SLPrint(&s);
    	//SLPopFront(&s);
    	//SLPrint(&s);
    	//SLPopFront(&s);
    	//SLPrint(&s);
    	//SLPopFront(&s);
    	//SLPrint(&s);
    
    	SLInsert(&s, 11, 0);
    	SLPrint(&s);
    	SLInsert(&s, 22, s.size);
    	SLPrint(&s);
    	SLInsert(&s, 33, 1);
    	SLPrint(&s);
    
    	SLDestroy(&s);
    }
    
    int main()
    {
    	SLtest01();
    	return 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值