数据结构顺序表C语言实现(无废话,代码纯享版)

目录

顺序表创建

顺序表初始化

顺序表扩容

顺序表头插

顺序表头删

顺序表尾插

顺序表尾删

顺序表销毁

顺序表打印

指定位置查找

指定位置插入

指定位置删除


由于本人水平知识有限,文章难免有错误的地方,如有错误或不理解的地方,请评论或私信与我联系,若本文帮助到你的话,请给我一个赞吧,谢谢!

测试平台:VS2022

使用时直接将全部代码复制到编译器即可

顺序表本质就是数组,其在数组中存储必须是连续的,顺序表就是在数组的基础上实现增删查改,并且插入时可以实现动态增长

缺点:中间或头部的插入删除很慢,需要挪动数据(时间复杂度O(N));空间不够时,增容会有一定的消耗和空间浪费以及效率损失

优点:可以随机访问;缓存命中率较高,(因为物理空间连续,预加载有优势)

顺序表创建

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLDataType; //为什么要定义这一行?方便以后修改类型

// 动态顺序表
typedef struct SeqList
{
	SLDataType* a;  //用指针指向动态开辟的空间
	int size;      // 表示数组中存储了多少个数据
	int capacity;  // 数组实际能存数据的空间容量是多大 
}SL;


// 接口函数 -- 命名风格是跟着STL走的,方便后续学习STL
void SeqListPrint(SL* ps);//打印

void SeqListInit(SL* ps); // 顺序表初始化

void SeqListDestory(SL* ps);//销毁

void SeqListCheckCapacity(SL* ps);//扩容

void SeqListPushBack(SL* ps, SLDataType x);//尾插

void SeqListPopBack(SL* ps);//尾删

void SeqListPushFront(SL* ps, SLDataType x);//头插

void SeqListPopFront(SL* ps);//头删

int SeqListFind(SL* ps, SLDataType x);// 找到了返回x位置下标,没有找到返回-1

void SeqListInsert(SL* ps, int pos, SLDataType x);// 指定pos下标位置插入

void SeqListErase(SL* ps, int pos);// 删除pos位置的数据

顺序表初始化

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

顺序表扩容

void SeqListCheckCapacity(SL* ps)
{
	// 如果没有空间或者空间不足,那么我们就扩容
	if (ps->size == ps->capacity)
	{
        //三目运算符,如果capacity是0就给它4个字节空间,如果不是就扩容2倍
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; 
		
        //用realloc扩容一块新的内存空间,注意newcapacity * sizeof(SLDataType)是字节数
        SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		
        if (tmp == NULL)//如果申请空间失败就退出函数
		    {
			    printf("realloc fail\n");
			    exit(-1);//表示异常退出
		    }

		    ps->a = tmp;
		    ps->capacity = newcapacity;
	}
}

顺序表头插

void SeqListPushFront(SL* ps, SLDataType x)
{
	//第一种方法
	//SeqListCheckCapacity(ps);
	 挪动数据
	//int end = ps->size - 1;
	//while (end >= 0)
	//{
	//	ps->a[end + 1] = ps->a[end];
	//	--end;
	//}
	//ps->a[0] = x;  //在头部插入节点
	//ps->size++;

	SeqListInsert(ps, 0, x);  //第二种方法,复用SeqListInsert实现
}

顺序表头删

void SeqListPopFront(SL* ps)
{
	assert(ps->size > 0);

	 挪动数据第一种方法
	//int begin = 1;           //0
	//while (begin < ps->size) //size-1
	//{
	//	ps->a[begin - 1] = ps->a[begin];//begin+1
	//	++begin;
	//}
	//ps->size--;

	SeqListErase(ps, 0); //第二种方法复用SeqListErase
}

顺序表尾插

void SeqListPushBack(SL* ps, SLDataType x)
{
	/*SeqListCheckCapacity(ps);//第一种方法直接实现
	ps->a[ps->size] = x;
	ps->size++;*/

	SeqListInsert(ps, ps->size, x);//复用SeqListInsert实现
}

顺序表尾删

void SeqListPopBack(SL* ps)
{	
	//空了就不能再删除
	// 第一种方法温柔处理方式,啥都不做
	//if (ps->size > 0)
	//{
	//	//ps->a[ps->size - 1] = 0; 
	//	ps->size--;
	//}

	// 第二种方法暴力处理方式
	//assert(ps->size > 0);//断言终止程序
	//ps->size--;

	SeqListErase(ps, ps->size - 1);//复用SeqListErase
}

顺序表销毁

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

顺序表打印

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

指定位置查找

int SeqListFind(SL* ps, SLDataType x)
{
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;//如果没有找到就返回-1
}

指定位置插入

// 指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x)
{
	// 越界了温柔的处理方式
	/*if (pos > ps->size || pos < 0)
	{
		printf("pos invalid\n");
		return;
	}*/

	// 越界了粗暴的方式
	assert(pos >= 0 && pos <= ps->size);
	SeqListCheckCapacity(ps);
	// 挪动数据
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}
	ps->a[pos] = x;
	ps->size++;
}

指定位置删除

// 删除pos位置的数据
void SeqListErase(SL* ps, int pos)
{
	assert(pos >= 0 && pos < ps->size);
	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		++begin;
	}
	ps->size--;
}

代码调试

void TestSeqList()
{
	SL sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);

	SeqListPopBack(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);

	SeqListPushFront(&sl, 10);
	SeqListPushFront(&sl, 20);
	SeqListPrint(&sl);

	SeqListPopFront(&sl);
	SeqListPopFront(&sl);
	SeqListPrint(&sl);

	int z=SeqListFind(&sl, 2);//找下标为2的元素
	printf("%d\n", z);

	int pos = SeqListFind(&sl, 3); //指定为3的元素删除
	if (pos != -1)
	{
		SeqListErase(&sl, pos);
	}
	SeqListPrint(&sl);

	SeqListInsert(&sl, 2, 100);//在下标为2的地方插入100
	SeqListPrint(&sl);
	void SeqListDestory(SL * ps);
}


int main()
{
	TestSeqList();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值