ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数据结构——顺序表

2021-12-16 18:03:06  阅读:197  来源: 互联网

标签:ps 顺序 SeqList 元素 array 数据结构 size


文章目录


前言

在这里插入图片描述


一、顺序表

1.灵魂三连击:咋来的?啥玩意?有啥用?

先来说一说咋来的: 你敲代码需要定义数据(字符串、数组、阿巴阿巴)吗?
在这里插入图片描述
所以理所应当就会有线性表这个概念??????线性表(linear list)是n个具有相同特性的数据元素的有限序列。顺序表也是线性表的一种,最常见的数组也算~~~算吗?我也具体忘记了,这无伤大雅!

再来说一说啥玩意: 顺序表就是数据按顺序结构在一段连续的空间上进行存储!
数据是顺序结构连续的1,2,3,4,5,6,蓝色框就是传说中的连续内存空间
顺序表有什么卵用?: 对连续的数据进行操作。以满足实际工作中的需求,比如需要在连续顺序的数据中插入一个数,变成这样
在这里插入图片描述

2.这玩意这么实在,怎么用?

当然就是要创建了!!顺序表分为静态和动态两种,静态的话参考数组,没啥说的,如果有,那就不说了
在这里插入图片描述

3.那就来看看动态顺序表是个什么东西?如何创建?

动态顺序表------底层空间从堆上动态申请出来的! 底层空间?堆?可以看看这个文章C 语言函数中栈帧的创建与销毁

typedef struct SeqList {	//自定义结构体SeqList,里面包含三个变量
	DataType* array;		//指向存储元素空间的起始位置
	int capacity;	//表示空间总的大小
	int size;           //有效元素的个数
}SeqList;

//对array,capacity,size进行初始化设置
//Struct SeqList S;
//	S.array :10
//	S.capacity :10
//	S.size :

原理如下:
在这里插入图片描述

二、顺序表操作

1.操作声明

什么是对顺序表的操作?就是在上面定义好的顺序表中对其进行元素的增删查找。都有哪些呢?

//初始化ps(对指向顺序表的指针进行初始化操作)
void SeqListInit(SeqList* ps, int initCapacity);
//销毁(对顺序表进行销毁)
void SeqListDestory(SeqList* ps);
//尾插(在顺序表最后面加入元素)
void SeqListPushBack(SeqList* ps, DataType data);
//尾删(删除顺序表最后的元素)
void SeqListPopBack(SeqList* ps);
//头插(在顺序表最前面加入元素)
void SeqListPushFront(SeqList* ps, DataType data);
//头删(删除顺序表第一个元素)
void SeqListPopFront(SeqList* ps);
//在顺序表的pos位置插入元素data
// 注意pos的范围必须在[0,ps->size]
void SeqListInsert(SeqList* ps, int pos, DataType data);
//删除pos位置的值
// 注意pos范围
void SeqListErase(SeqList* ps, int pos);
//有效元素的个数
int SeqListSize(SeqList* ps);
//空间总的大小
int SeqListCapacity(SeqList* ps);
//返回空间中某个元素的位置
void SeqListFind(SeqList* ps, DataType data);
//检查顺序表是否为空
int SeqListEmpty(SeqList* ps);
//获取顺序表中第一个元素
DataType SeqListFront(SeqList* ps);
//获取顺序表中最后一个元素
DataType SeqListBack(SeqList* ps);
//获取顺序表任意一个位置元素
DataType SeqListGet(SeqList* ps,int pos);
//打印顺序表
void SeqListPrint(SeqList* ps);
//测试顺序表
void TestSeqList();

2.具体操作定义

初始化: 先从堆上申请一块内存空间用以存储数组。先利用malloc申请空间initCapacity,

//将ps指向的结构体变量初始化成功
void SeqListInit(SeqList* ps, int initCapacity) {        //检测一下指针参数ps,防止取空
	assert(ps); 
	ps->array = (int*)malloc(initCapacity * sizeof(int));//申请一块内存用以村存储数组 
	//检测生成是否成功
	if (NULL == ps->array) {  //检测指针ps指向申请的内存空间中存放的数组首元素地址是否存在
		assert(0);
		return;
	}
	ps->capacity = initCapacity; //指针ps指向的capacity初始化为申请的内存空间
	ps->size = 0; //初始化内存空间中的元素个数
}

销毁: 销毁顾名思义就是之前在堆上申请了内存空间用以存储顺序表,现在这个顺序表结束了它的使命,就要将申请的空间进行释放,否则久而久之,申请的内存空间过多而没有销毁会出现所谓的内存泄漏
在这里插入图片描述

//将ps指向的结构体变量销毁
void SeqListDestory(SeqList* ps){
	assert(ps);
	if (ps->array) {
		free(ps->array);//释放申请的内存
		ps->array = NULL;//释放后,数组清空
		ps->capacity = 0;//申请的内存空间清零
		ps->size = 0;//元素个数清零
	}
}

尾插: 这里需要注意的是,你要在array的末尾插入元素,得有地方给你插,因为原来capacity已经给定了空间为10,array有10个元素数量。能插的地方有10个,10个都满了,需要扩容才能继续在后面插入元素。
在这里插入图片描述

在这里插入图片描述

//尾插
void SeqListPushBack(SeqList* ps, DataType data) {
	assert(ps);

	//1.检查空间是否足够
	CheckCapacity(ps);
	//2.在最后一个元素之后插入data
	ps->array[ps->size] = data;//ps指向size的位置恰好是元素个数,同时是尾插的存储位置
	ps->size++;//由于加入一个元素,导致size增加1
}

检查空间是否足够: 这里不用多说,尾插中由于需要有足够的空间,所以要检查

//检查容量进行扩容
void CheckCapacity(SeqList* ps) {
	assert(ps);
	if (ps->size == ps->capacity) { //元素的个数和申请的内存空间个数相等,说明需要扩容
		int newCapacity = (ps->capacity << 1);//定义一个新的空间newCapacity在原空间上左移1(左移扩大两倍)
		DataType* temp = (DataType*)malloc(sizeof(DataType) * newCapacity);//为newCapacity申请内存空间,指针temp
		if (NULL == temp) {
			exit(0);
			return;
		}
		//memcpy
		for (int i = 0; i < ps->size; ++i) { //令指针temp代替指针原指针ps的位置
			temp[i] = ps->array[i];
		}
		//对原内存空间进行释放,使用新的内存空间
		free(ps->array);
		ps->array = temp;
		ps->capacity = newCapacity;
	}
}

尾删: 尾删很简单,零数组array的size数量减 1 就行。不过在这里需要检测顺序表是否为空,空的话拿头给你删?

//尾删
void SeqListPopBack(SeqList* ps) {
	assert(0);

	//1.要检查是否为空,为空直接返回,有元素删除
	//if (0 == ps->size) {
	//	return;
	//}
	
	//添加函数检测顺序表是否为空
	if (SeqListEmpty(ps)) {
		return;
	}
	ps->size--;
}

检测顺序表是否为空(判空): 这里就是对尾删里面那个判空进行的填坑。

//判空
int SeqListEmpty(SeqList* ps) {
	assert(ps);
	return 0 == ps->size;//size如果等于0的话,与0相等,此表达式为真。返回真
}

头插: 与尾插类似,不同点在于需要对整个元素向后进行搬移,然后第一个位置空出来进行头插
在这里插入图片描述

//头插
void SeqListPushFront(SeqList* ps, DataType data) {
	assert(ps);

	//1.检测空间是否足够
	CheckCapacity(ps);
	//2.将顺序表中的所有元素整体向后搬移一位
	for (int i = ps->size - 1; i >= 0; --i) {
		ps->array[i + 1] = ps->array[i]; //原来array[i]的位置变成现在array[i+1]的位置
	}
	//3.插入元素
	ps->array[0] = data;
	ps->size++;
}

头删:

//头删
void SeqListPopFront(SeqList* ps) {
	//判空
	if (SeqListEmpty(ps)) {
		return;
	}
	//将顺序表中除第一个元素外往前搬
	for (int i = 0; i < ps->size - 1; i++) {
		ps->array[i] = ps->array[i + 1];
	}ps->size--;
}

在顺序表的pos位置插入元素data:(注意pos的范围必须在[0,ps->size]) 这里的原理就是把pos位置前的元素不管,然后,pos位置之后包括pos位置的元素进行头插

在这里插入图片描述

void SeqListInsert(SeqList* ps, int pos, DataType data) {
	//1.参数检测
	assert(ps);
	if (pos < 0 || pos > ps->size) {
		printf("pos的位置有问题");
		return;
	}
	//2.检测是否需要扩容
	CheckCapacity(ps);
	//3.插入元素
	for (int i = ps->size - 1; i >= pos; i--) {
		ps->array[i+1] = ps->array[i];
	}
	ps->array[pos] = data;
	ps->size++;
}

删除pos元素位置的值: 同样的,pos之后的元素向前进行头删

void SeqListErase(SeqList* ps, int pos) {
	assert(ps);
	if (pos < 0 || pos >= ps->size) {
		printf("位置有问题");
		return;
	}
	if (SeqListEmpty(ps)) { //判空,元素不能为空,才能进行某一位置的删除
		return;
	}
	for (int i = pos + 1; i < ps->size; ++i) {
		ps->array[i - 1] = ps->array[i];
	}
	ps->size--;
}

其他: 包括有效元素个数的定义(定义顺序表中有几个有效元素),空间总的大小定义,返回空间中某个元素的位置(从前往后进行遍历,遍历的值 i == data时,输出 i),获取顺序表中的元素(首元素,尾元素,任意位置元素),打印顺序表,测试顺序表。这些都比较简单,统一列举出来

//有效元素的个数
int SeqListSize(SeqList* ps) {
	assert(ps);
	return ps->size; //有效元素个数就是size之前的所有 array 中的元素
}
//空间总的大小
int SeqListCapacity(SeqList* ps) {
	assert(ps);
	return ps->capacity; //空间总的大小就是 capacity
}
//返回空间中某个元素的位置
int SeqListFind(SeqList* ps, DataType data) {
	assert(ps);
	for (int i = 0; i < ps->size; i++) { //i从0到有效元素进行遍历,
		if (ps->array[i] == data) { //遍历到的值 == data 时,得到位置i
			return i;
		}
	}return -1;
}

//获取顺序表中第一个元素
DataType SeqListFront(SeqList* ps) {
	assert(ps);
	return ps->array[0];
}
//获取顺序表中最后一个元素
DataType SeqListBack(SeqList* ps) {
	assert(ps);
	return ps->array[ps->size - 1];
}
//获取顺序表任意一个位置元素
DataType SeqListGet(SeqList* ps, int pos) {
	assert(ps);
	return ps->array[pos];
}

//打印顺序表
void SeqListPrint(SeqList* ps) {
	assert(ps);
	for (int i = 0; i < ps->array; ++i) {
		printf("%d ", ps->array[i]);//打印数组中所有的元素
	}printf("\n");
}

总结

上面总结的很详细了,还总结??我跟在座的各位总结个

标签:ps,顺序,SeqList,元素,array,数据结构,size
来源: https://blog.csdn.net/lmh23333/article/details/121975466

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有