C语言:顺序表的实现

标题C语言实现顺序表

线性表的定义

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串

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

在这里插入图片描述

在这里插入图片描述

顺序表的定义

顺序表时用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。可分为静态顺序表动态顺序表

1、静态顺序表:使用定长数组存储元素

在这里插入图片描述

2、动态顺序表:使用动态开辟的数组存储

在这里插入图片描述

顺序表的实现

顺序表要实现的函数如下,此处我们实现动态顺序表

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define INIT_SIZE 4
// 定义顺序表的数据类型
typedef int SeqType;

// 定义一顺序表的结构体
typedef struct Seqlist {
	SeqType* list;
	int size;
	int capacity;
} Seqlist;

// 初始化顺序表
void SeqInit(Seqlist* sl);
//  尾插数据
void SeqListPushBack(Seqlist* sl, SeqType x);
// 头插数据
void SeqListPushFront(Seqlist* sl, SeqType x);
// 尾删数据
void SeqListPopBack(Seqlist* sl);
// 头删数据
void SeqListPopFront(Seqlist* sl);
// 清除顺序表
void SeqListDistory(Seqlist* sl);
// 顺序表查找
int SeqListFind(Seqlist* sl, SeqType x);
// 顺序表在pos位置插入x
void SeqListInsert(Seqlist* sl, size_t pos, SeqType x);
// 顺序表删除pos位置的值
void SeqListErase(Seqlist* sl, size_t pos);
// 显示顺序表
void SeqListPrint(Seqlist* sl);
// 顺序表扩容
void SeqListDilation(Seqlist* sl);
// 判断顺序表是否为空
int SeqListIsEmpty(Seqlist* sl);

在我们要使用顺序表时,就先创建一个顺序表的变量Seqlist sl,有了变量之后,我们就得要初始化这个顺序表,就是将结构Seqlist的成员初始化。

// 初始化顺序表
void SeqInit(Seqlist* sl) {
	sl->list = NULL;
	sl->size = 0;
	sl->capacity = 0;
}

在对顺序表进行操作的时候都得判断它是否为空

// 判断顺序表是否为空
int SeqListIsEmpty(Seqlist* sl) {
	assert(sl);
	if (sl->size == 0) {
		return 1;
	}
	else {
		return 0;
	}
}

我们知道,顺序表的主要操作就是增、删、改、查,我们下面逐一实现。因为我们这个顺序表的长度是不确定的。就是说,我们在最开始使用时会先在内存空间为它申请一块空间,当我们把这块空间用完,就需要对顺序表进行扩容,扩容代码如下。

// 顺序表扩容
void SeqListDilation(Seqlist* sl) {
	assert(sl);
	int sz = sl->capacity == sl->size && sl->capacity != 0 ? sl->capacity * 2 : INIT_SIZE;  // 第一次申请空间为4,不是第一次扩容到capacity的2倍
	if (sl->size == sl->capacity) { // 判断是否需要扩容
		SeqType* tmp = (SeqType*)realloc(sl->list, sizeof(SeqType) * sz);
		sl->list = tmp;
	}
	sl->capacity = sz;
}

解决了顺序表扩容的问题,我们就开始进行增删改查

向顺序表中插入数据有三种方式–头插法、尾插法、随机插入

尾插法很简单,就相当于接着在数组后面添加数据,而顺序表中,size所在的位置就是最后一个数据的后一个位置。

// 向顺序表中添加数据(尾插)
void SeqListPushBack(Seqlist* sl, SeqType x) {
	assert(sl);
	SeqListDilation(sl);
	sl->list[sl->size] = x;
	sl->size++;
}

头像在每次插入数据后就得将数组整体往后移动一位

// 向顺序表中添加数据(头插)
void SeqListPushFront(Seqlist* sl, SeqType x) {
	assert(sl);
	SeqListDilation(sl);
	int i = 0;
	for (i = sl->size; i > 0; i--) {
		sl->list[i] = sl->list[i - 1];
	}
	sl->list[0] = x;
	sl->size++;
}

所谓随机插入,就是我们指定一个位置,将数据插入进去

// 顺序表在pos位置插入xvoid SeqListInsert(Seqlist* sl, size_t pos, SeqType x) {
	assert(sl);
	SeqListDilation(sl);
	int index = pos > sl->size ? sl->size : pos;
	int i = 0;
	for (i = sl->size; i > index; i--) {
		sl->list[i] = sl->list[i - 1];
	}
	sl->list[pos] = x;
	sl->size++;
}

删除数据也有三种方法–头删、尾删、随机删除

尾删就是让最后一个元素不被访问到,就行了

// 从顺序表中删除一个数据(尾删)
void SeqListPopBack(Seqlist* sl) {
	assert(sl);
	sl->size--;
}

头删要将除了第一个元素以外的数据全都向前移动一位,后面的数据把前面的数据覆盖掉

// 从顺序表中删除一个数据(头删)
void SeqListPopFront(Seqlist* sl) {
	assert(sl);
	int i = 0;
	for (i = 0; i < sl->size; i++) {
		sl->list[i] = sl->list[i + 1];
	}
	sl->size--;
}

随机删除就是删除我们指定位置的数据

// 顺序表删除pos位置的值
void SeqListErase(Seqlist* sl, size_t pos) {
	assert(sl);
	if (SeqListIsEmpty(sl) == 1) {
		exit(-1);
	}
	int index = pos > sl->size ? sl->size - 1 : pos;
	int i = 0;
	for (i = index; i < sl->size; i++) {
		sl->list[i] = sl->list[i + 1];
	}
	sl->size--;
}

从顺序表中查找数据

这里的方法是便利顺序表,从中找到我们想要的值。找到了就返回它的下标,否则返回-1

// 顺序表查找
int SeqListFind(Seqlist* sl, SeqType x) {
	assert(sl);
	if (SeqListIsEmpty(sl) == 0) {
		exit(-1);
	}
	int i = 0;
	for (i = 0; i < sl->size; i++) {
		if (sl->list[i] == x) {
			return i;
		}
	}

	return -1;
}

打印顺序表,将顺序表遍历一遍打印出来

// 显示顺序表
void SeqListPrint(Seqlist* sl) {
	assert(sl);
	int i = 0;
	for (i = 0; i < sl->size; i++) {
		printf("%d ", sl->list[i]);
	}
}

在使用完顺序表之后我们将它清理掉

// 清除顺序表
void SeqListDistory(Seqlist* sl) {
	assert(sl);
	free(sl->list);
	sl->list = NULL;
	sl->size = 0;
	sl->capacity = 0;
}

—end

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_yiyi_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值