数据结构───顺序表(梦开始的地方)

  从一个编程小白到入门,大学选的软件工程,从大一开始就没有真正的了解这个专业,更别说以后的发展方向。活了几十年,也不知道自己究竟要成为一个什么样的人。似乎在大二的某一天,忽然意识到我不该如此庸碌下去,是时候该改变和提升自己了。于是我做了两件事,读了两本书,一本《月亮与六便士》,一本《认知觉醒》,第二件事徒步登顶华山。于是我逐渐意识到,我一直是那个呆在山下仰望山顶的人,思想是分阶层的,一旦一个人的思维上了一个维度,就很难再降下去。

数据结构───顺序表(梦开始的地方)_第1张图片

  后来我在从零开始的学习过程中,遇到了许多行业精英,编程高手,太多优秀的人以至于自己也想成为一个更好的人。 种一棵树最好的时间是十年前,其次实现。

数据结构───顺序表(梦开始的地方)_第2张图片

   我写博客只是便利自己。因为遗忘一种自然现象,在未来的某一天,我一定会对某些东西模糊,这时候就可以回来翻翻自己的博客啦。

 

什么是顺序表? 

简单来说,就是按顺序依次存储简单元素的线性数据结构,数组就是顺序表。其实目前我还不知道除了数组还有哪个数据结构是顺序表emmm。

 如何实现顺序表

   那么创建一个顺序表就是定义一个数组吗?其实不止这些。顺序表不仅要存储数据,得实现数据的增删查改吧。所以就需定义另一个变量,来记录数组的元素下标,来实现以上功能。顺序表就分为两种,一种静态,一种动态。动态就需要多一个变量,来记录当前的最大容量。

typedef int SLDataType;//顺序表要存储的类型
#define N 100
//创建数据结构--顺序表--静态
typedef struct SqeList {
	SLDataType a[N];
	int size;        //记录当前数据个数
}SL;


//创建数据结构--顺序表--动态
typedef struct SqeList {
	SLDataType* a;
	int size;        //记录当前数据个数
	int capacity;    //顺序表最大容量
}SL;

下面就动态顺序表各个功能的实现,因为动态会了,静态自然就会了。

 首先初始化顺序表

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

 然后实现插入元素功能,只要添加数据就需要先检查内存够不够,于是先实现增容功能。

//扩容
void SqeListCheckCapacity(SL* ps) {
	if (ps->size == ps->capacity) {
		int newcapacity = ps->capacity == 0 ? SIZEINIT : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (tmp == NULL) {
			perror("no space to use:");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}
//插入元素
void SqeListInsert(SL* ps, int pos, SLDataType x) {
	SqeListCheckCapacity(ps);
	assert(pos >=0 && pos <= ps->size);
	memmove(ps->a+pos+1, ps->a+pos, (ps->size - pos) * sizeof(SLDataType));
	ps->a[pos] = x;
	ps->size++;
}

 插入功能完成了,那么头插尾插直接调用即可。

数据结构───顺序表(梦开始的地方)_第3张图片

//尾部插入一个数据
void SqeListPushBack(SL* ps,SLDataType x) {
	/*SqeListCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;*/

	SqeListInsert(ps, ps->size, x);
}
//顶部插入一个数据
void SqeListPushFront(SL* ps,SLDataType x) {
	//SqeListCheckCapacity(ps);
	//int end = ps->size - 1;
	//while (end >= 0) {
	//	ps->a[end + 1] = ps->a[end];
	//	end--;                  
	//}
	//ps->a[0] = x;
	//ps->size++;
	SqeListInsert(ps, 0,x);
}

 删除元素的话,只要将要删除的元素覆盖掉,可以使用memmove函数,当然也可以写个循环一个一个的移。

//删除尾部数据
void SqeListPopBack(SL* ps) {
	assert(ps->size > 0);
	ps->size--;
}
//删除顶部数据
void SqeListPopFront(SL* ps) {
	assert(ps->size > 0);
	//法一:
	//int begin = 1;
	//while (begin > ps->size) {
	//	ps->a[begin - 1] = ps->a[begin];
	//	begin++;
	//}
	//ps->size--;
	//法二:
	memmove(ps->a, ps->a + 1, (ps->size - 1) * sizeof(SLDataType));
	ps->size--;
}

 接下来实现一下查找,直接暴力枚举,遍历一遍顺序表所有元素。

//查找
int SqeListFind(SL* ps, SLDataType x) {
	for (int i = 0; i < ps->size; i++) {
		if (ps->a[i] == x) {
			return i;
		}
	}
	return -1;
}

对于修改功能,直接赋值就好啦。还有排序功能,各种排序方法,因地适宜。最后也是最重要的,用realloca开辟的空间要归还,避免内存遗漏 ,养成好习惯,同时也将指针赋空。

//顺序表销毁
void SqeListDestory(SL* ps) {
	free(ps->a);
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

这就是一个简单动态顺序表的实现了。检验所学知识当然就是刷题啦

数据结构───顺序表(梦开始的地方)_第4张图片

直接打开leetcode找到数组一栏,对于初学者就从简单开始。1. 两数之和 - 力扣(LeetCode)

 题目要求在一个数组中返回两个数的下标,这两个数相加等于目标值。对于没有接触高阶算法的我来说,直接暴力枚举就好啦,如果相等就返回两数下标。


int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    *returnSize=2;
    int*pc=(int*)malloc(2*sizeof(int));
    for(int i=0;i

  由于接收端会释放内存,我就不用释放了,对于初学者能过就行啦,好了,完成第一题现在我也是刷过leetcode的人了,但想要不断巩固和熟练掌握所学内容,就采用刷题的方式,因为每一次通过就是给自己一次的正向反馈,等自己知识储备一定多的时候,再返回来试着用不同的方法解决,优化时间复杂度和空间复杂度。

数据结构───顺序表(梦开始的地方)_第5张图片

你可能感兴趣的:(数据结构与算法,数据结构)