数据结构与算法从0开始第一集:顺序表实现

先展示代码声明部分

头文件SeqList.h:

#define _CRT_SECURE_NO_WARNINGS
#pragma once//防止多重包含头文件导致重定义错误或者链接编译失败
#include <stdio.h>
#include <stdlib.h>


typedef int SLDatatype;//动态定义数据存储类型,方便修改
typedef struct SeqList
{
	int size;//表示存储了多少个数据元素
	int capacity;//表示表的存储空间大小
	SLDatatype* a;//表示表的头指针
}SL;//简写成SL

void SLInit(SL* sl);//初始化函数
void SLDestroy(SL* sl);//回收函数
void SLPushBack(SL* sl,SLDatatype x);//头插函数
void SLPushFront(SL* sl, SLDatatype x);//尾插函数
void SLPopBack(SL* sl);//头删函数
void SLPopFront(SL* sl);//尾删函数
void SLPrint(SL* sl);//打印函数
void SLCheckCapacity(SL* sl);//检查存储空间大小函数
void SLInsert(SL* sl, int pos, SLDatatype x);//插入指定位置元素函数
void SLErase(SL* sl, int pos);//删除指定位置函数
int SLFind(SL* sl, SLDatatype x);//查找函数
void SLModify(SL* sl, int pos, SLDatatype x);//修改函数

函数实现部分SeqList.c:

#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"
#include <assert.h>//导入断言头文件

void SLInit(SL* sl)
{
    assert(sl);
	sl->a = (SLDatatype*)malloc(sizeof(SLDatatype)*4);
	if (sl->a == NULL)//检查malloc函数是否开辟空间成功,该函数如果开辟失败返回空指针
	{
		perror("malloc fail");
		exit(1);//我的建议使用exit而不是return,因为return会引起void返回值警告
	}
	sl->capacity = 0;//开始时全部初始化为0
	sl->size = 0;
}
void SLDestroy(SL* sl)
{
	free(sl->a);//释放掉头指针
	sl->a = NULL;//将相关元素全部清零
	sl->capacity = 0;
	sl->size = 0;
}

void SLPushBack(SL* sl, SLDatatype x)
{
	assert(sl);
	SLCheckCapacity(sl);//在所有插入函数插入逻辑执行之前先进行存量检查
	sl->a[sl->size++] = x;
}

void SLPushFront(SL* sl, SLDatatype x)
{
	assert(sl);
	SLCheckCapacity(sl);
	int end = sl->size-1;//这里从后往前依次挪动
	while (end >= 0)
	{
		sl->a[end + 1] = sl->a[end];
		end--;
	}
	sl->a[0] = x;
	sl->size++;
} 

void SLCheckCapacity(SL* sl)
{
	if (sl->size == sl->capacity)
	{
        //这里使用三目操作符,表示如果容量为0,则设为4,如果不为零则扩容两倍
		int newcapacity = sl->capacity == 0 ? 4 * sizeof(SLDatatype) : sl->capacity * 2;
		SLDatatype* tmp = (SLDatatype*)realloc(sl->a, newcapacity);
        //这里在原来的基础上扩容建议使用realloc函数,该函数会查看原地址后面是否有足够空间,
        如果有则原地扩容,如果没有则进行复制拷贝到新的大内存块中返回新地址
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(2);
		}
		sl->a = tmp;
		sl->capacity = newcapacity;
	}
}

void SLPopBack(SL* sl)
{
	assert(sl && sl->size > 0);//防止空的情况
	sl->size--;//这里只需要讲size减掉让代码访问不到即可
}

void SLPopFront(SL* sl)
{
	assert(sl && sl->size > 0);//防止空的情况
	int start = 0;
	while (start < sl->size - 1)
	{
		sl->a[start] = sl->a[start + 1];
		start++;
	}
	sl->size--;
}

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

void SLInsert(SL* sl, int pos, SLDatatype x)
{
	assert(sl && pos <= sl->size);  // 确保顺序表非空,并且插入位置合法
	SLCheckCapacity(sl);  // 检查是否需要扩容
	int end = sl->size - 1;

	// 从最后一个元素开始向后移动,直到到达插入位置
	while (end >= pos)
	{
		sl->a[end + 1] = sl->a[end];
		end--;
	}

	sl->a[pos] = x;  // 在指定位置插入新元素
	sl->size++;  // 更新顺序表的大小
}
void SLErase(SL* sl, int pos)
{
	assert(sl && sl->size > 0 && pos < sl->size);  // 确保顺序表非空,且位置合法
	for (int i = pos; i < sl->size - 1; i++)
	{
		sl->a[i] = sl->a[i + 1];  // 将删除位置之后的元素向前移动
	}
	sl->size--;  // 更新顺序表的大小
}

// 查找函数:查找指定值的元素,并返回其索引
int SLFind(SL* sl, SLDatatype x)
{
	assert(sl);  // 确保顺序表不为空
	for (int i = 0; i < sl->size; i++)
	{
		if (sl->a[i] == x)
		{
			return i;  // 找到匹配的值,返回其索引
		}
	}
	return -1;  // 如果没找到,返回 -1
}

// 修改函数:将指定位置的元素修改为新的值
void SLModify(SL* sl, int pos, SLDatatype x)
{
	assert(sl && pos < sl->size);  // 确保顺序表不为空,且位置合法
	sl->a[pos] = x;  // 修改指定位置的元素
}

调用测试部分test.c

#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"

int main()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 3);
	SLPushFront(&s, 0);
	SLPopBack(&s);
	SLPopFront(&s);
	SLInsert(&s, 1, 4);
	SLErase(&s, 1);
	SLModify(&s, 1, 3);
	SLPrint(&s);
	SLDestroy(&s);
	return 0;
}

  测试结果如图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值