顺序表的代码实现以及写的过程中遇到的问题及解决方法。(1)

读者须知:本文章仅做为博主的笔记,抛砖引玉,代码实现上不完全,也无法完全考虑各种要素,有时间会补充。

注:博主大一新生,请多指教。

1.用数组充当循序表

int *list;//数组
//开辟空间时用list来指向。

问题:数组长度固定,我存的数据不一定是你的长度,用户瞎搞怎么办?

so

int *list;//数组
int count;//记录当前元素个数

属性增加

typedef struct ArrayList{
    int* list;
    int count;
};

问题:好像还不够,你数组总容量有多少呢?没有总容量我咋知道越没越界呢?

so

typedef struct ArrayList{
    int* list;
    int count;
    int maxSize;//加个总容量
}List;
//typedef使这里的struct ArrayList定义为List

//我还可以定义指针如
/*
typedef struct ArrayList{
    int* list;
    int count;
    int maxSize;//总容量
}List,*List_str;
*/
//typedef使这里的struct ArrayList*定义为List

上面所有的属性构成整个的顺序表。

2.做顺序表

(1)初始化

为什么要初始化?因为我(用户)不可能只用一个顺序表,需求很多的,所以我用一个就初始化一个呗。

List* initList(){
    List* list = (List*)malloc(sizeof(List));
	list->count = 0;
	list->maxSize = 5;//随便给,改的时候让用户传个就行,当然用户大概率不会,定义一个扩容函数//呗
	list->list = (int*)malloc(sizeof(int)*5);
	return list;
    
}

这时,你的IDE(我用的VS)可能会给警告。

如下,

 这是因为在写代码时,没有加判断内存分配是否分配成功的语句造成的。

 so,判断一下呗

List* initList(){
    List* list = (List*)malloc(sizeof(List));
    if (list == NULL) {
		return fail;//对于这个fail,前面加个宏定义就行
	}
	else {
		list->count = 0;
		list->maxSize = 5;//随便给,改的时候让用户传个就行,当然用户大概率不会,定义一个扩容函数//呗
		list->list = (int*)malloc(sizeof(int)*5);
	}
	return list;
    
}

初始化完成。

(2)增删改查来吧

增:也就是插入,要插入的话,我们需要插入的值,以及插哪个表。

void insert(int key,List*list){//key是传入的值
    
}

需要考虑,我们是否允许数据重复

假如我们现在是一个数据不重复的状态,注:以下全是该状态。

我们插入之前,要判断能不能插入,

void insert(int key, List* list) {
	if (list->count < list->maxSize) {
        //没满,可以插

	}
	else {
		//提示满了,或者直接扩容
	}

}

如果是挨着插入,顺着插入,用当前元素个数当下标即可。

//顺着插入
void insert(int key, List* list) {
	if (list->count < list->maxSize) {
		list->list[list->count] = key;//当前元素个数初始化为0
		list->count++;
	}
	else {
		//提示满了,或者直接扩容
	}

}

如果是中间位置插入,这么搞?

在某个元素之前插入,我们就需要三个参数,插入什么元素,在哪个表,在哪个元素前插入。

你跟我说在哪个元素之前插入,我是不是得找一下看有没有啊。

void find(int key, List* list) {


}

我找到之后怎么办,要把数组往后移才有位置给插入的元素吧,所以我要知道这个位置,才能移动,所以返回下标。查找的话for循环就好了呗。

#define fail -1
int find(int key, List* list) {
	for (int i = 0; i < list->count; i++)
	{
		if (list->list[i] == key) {
			return i;//找到了,返回下标
		}

	}
	return fail;//都没找到,返回-1
}

查找可以了

和顺序插入一样,先判断有没有满,这里一口气写下来了。

//中间插入
void insert(int key, List* list,int data) {
	if (list->count < list->maxSize) {
		int index = find(list, data);//找下标
		if (index == -1) {
			//找不到,没有这个元素,退出吧
		}
		else {
			//先移动位置,先移后面的
			for (int i = list->count; i < index; i--)
			{
				list->list[i] = list->list[i - 1];

			}
			list->list[index] = key;
			list->count++;
		}

	}
	else {
		//提示满了,或者直接扩容
	}

}

跑一下看看吧

如果你把typedef那段代码放在main函数后面,那么你一定会报一堆的错误

#include<stdio.h>
#include<stdlib.h>
#define fail -1

typedef struct ArrayList {
	int* list;
	int count;
	int maxSize;//加个总容量
}List;

void insert_mid(int key, List* list, int data);
void insert(int key, List* list);
List* initList();
int find(int key, List* list);
void printfList(List* list);


int main() {
	List* list = initList();
	insert(1, list);
	insert(2, list);
	insert(3, list);
	insert(4, list);
	insert(5, list);
	printfList(list);


}





List* initList() {
	List* list = (List*)malloc(sizeof(List));
	if (list == NULL) {
		return fail;//对于这个fail,前面加个宏定义就行
	}
	else {
		list->count = 0;
		list->maxSize = 5;//随便给,改的时候让用户传个就行,当然用户大概率不会,定义一个扩容函数//呗
		list->list = (int*)malloc(sizeof(int) * 5);
	}
	return list;

}

//顺着插入
void insert(int key, List* list) {
	if (list->count < list->maxSize) {
		list->list[list->count] = key;//当前元素个数初始化为0
		list->count++;
	}
	else {
		//提示满了,或者直接扩容
	}

}

int find(int key, List* list) {
	for (int i = 0; i < list->count; i++)
	{
		if (list->list[i] == key) {
			return i;//找到了,返回下标
		}

	}
	return fail;//都没找到,返回-1
}

//中间插入
void insert_mid(int key, List* list,int data) {
	if (list->count < list->maxSize) {
		int index = find(data, list);//找下标
		if (index == -1) {
			//找不到,没有这个元素,退出吧
		}
		else {
			//先移动位置,先移后面的
			int i;
			for(i = list->count; i > index; i--)//如果死循环,可能会有定义错误的for-loop
			{
				list->list[i] = list->list[i - 1];

			}
			list->list[index] = key;
			list->count++;
		}

	}
	else {
		//提示满了,或者直接扩容
	}

}

void printfList(List*list) {
	for (int i = 0; i < list->count; i++) {//如果死循环,可能会有定义错误的for-loop
		printf("%d ", list->list[i]);
	}
	printf("\n");

}


当然你也可以这么玩,不过输出不如我意

 因为原来开辟的空间已经满了。

插入就先到这里了,还能写各种各样的插入,无非就是考虑下标、移动元素。

然后嘞

删除

插入考虑是否满的情况,那删除就考虑是否为空呗。空的删啥劲呢?

void delete_list(int key, List* list) {
	if (list->count == 0) {
		return;//有问题肯定都有给提示的,像我们用软件,出现问题了都有提示,用printf输出一下就可以
	}
	else {
		//如果有数据,找有没有要删除的数据
		int index = find(key, list);
		if (index == -1) {
			return;
		}
		else {
			//删除怎么删,单纯的移动,从当前下标往后走。把后一个元素给前面
			for (int i = index; i < list->count; i++) {
				list->list[i] = list->list[i + 1];
			}
			list->count--;
		}
	}
}

请注意:这里的删除不是真的删除,是伪的,只不过给用户呈现时看起来是删除了

比如我数组里有1 2 3 4这四个数据,我移完后是1 3 4 4,不过我count--了,又因为输出函数输出的时候是按count来输出的,所以给用户呈现的是1 3 4

 不建议复制粘贴,建议自己敲一下。

接下来是扩容,直接上代码

void enlargement(List*list) {
	//数组一定义,大小就已经定了,改不了,所以定义一个新数组
	int* temp = (int*)malloc(sizeof(int) * (list->maxSize + 5));
	//拷贝
	if (temp == NULL) {
		return;
	}
	else {
		for (int i = 0; i < list->maxSize; i++) {
			temp[i] = list->list[i];

		}
	}
	//拷贝完,我得让结构体里面的指针指向我新构建的数组
	//要还指向原来的这不白干了吗
	//list->list = temp;
	//但原来的数组我要释放掉,可是上一行指向完之后我就找不到原先的了
	//所以我要在定义一个指针变量。
	int* arraytemp = list->list;
	list->list = temp;
	//然后释放
	//free(arraytemp);
	//不过我们的部分属性还是原来的属性呀
	//改属性
	list->maxSize += 5;


	free(arraytemp);
}

如果发现如下图

 没事,这个警告不用管。

 注哦,我们原来数组长度只有5个int的大小。

但,扩容操作考虑了,缩容呢?

因为删除会浪费空间

比如我有5个长度,我插入1000个数据,那么你会扩容到1000个(当然,用代码实现循环不就可以了吗),那我再删除999个数据。

那现在1000长度的数组就用一个?太离谱了。

那缩减到一定程度,还要干掉这个空间。

代码怎么实现呢?

那就创建一个小数组呗,那减到什么程度呢,

以下是我的想法

用当前maxSize去减count再和5取余数,余数就是要缩短的次数。

你的想法呢?

下面给出没有考虑缩容的代码

#include<stdio.h>
#include<stdlib.h>
#define fail -1

typedef struct ArrayList {
	int* list;
	int count;
	int maxSize;//加个总容量
}List;

void insert_mid(int key, List* list, int data);
void insert(int key, List* list);
List* initList();
int find(int key, List* list);
void printfList(List* list);
void delete_list(int key, List* list);

int main() {
	List* list = initList();
	insert(1, list);
	insert(2, list);
	insert(3, list);
	insert(4, list);
	insert(5, list);
	insert(6, list);
	printfList(list);
	


	return 0;
}

void enlargement(List*list) {
	//数组一定义,大小就已经定了,改不了,所以定义一个新数组
	int* temp = (int*)malloc(sizeof(int) * (list->maxSize + 5));
	//拷贝
	if (temp == NULL) {
		return;
	}
	else {
		for (int i = 0; i < list->maxSize; i++) {
			temp[i] = list->list[i];

		}
	}
	//拷贝完,我得让结构体里面的指针指向我新构建的数组
	//要还指向原来的这不白干了吗
	//list->list = temp;
	//但原来的数组我要释放掉,可是上一行指向完之后我就找不到原先的了
	//所以我要在定义一个指针变量。
	int* arraytemp = list->list;
	list->list = temp;
	//然后释放
	//free(arraytemp);
	//不过我们的部分属性还是原来的属性呀
	//改属性
	list->maxSize += 5;


	free(arraytemp);
}

void delete_list(int key, List* list) {
	if (list->count == 0) {
		return;//有问题肯定都有给提示的,像我们用软件,出现问题了都有提示,用printf输出一下就可以
	}
	else {
		//如果有数据,找有没有要删除的数据
		int index = find(key, list);
		if (index == -1) {
			return;
		}
		else {
			//删除怎么删,单纯的移动,从当前下标往后走。把后一个元素给前面
			for (int i = index; i < list->count; i++) {
				list->list[i] = list->list[i + 1];
			}
			list->count--;
		}
	}
}



List* initList() {
	List* list = (List*)malloc(sizeof(List));
	if (list == NULL) {
		return fail;//对于这个fail,前面加个宏定义就行
	}
	else {
		list->count = 0;
		list->maxSize = 5;//随便给,改的时候让用户传个就行,当然用户大概率不会,定义一个扩容函数//呗
		list->list = (int*)malloc(sizeof(int) * 5);
	}
	return list;

}

//顺着插入
void insert(int key, List* list) {
	if (list->count < list->maxSize) {
		list->list[list->count] = key;//当前元素个数初始化为0
		list->count++;
	}
	else {
		//提示满了,或者直接扩容
		enlargement(list);
		list->list[list->count] = key;
		list->count++;
	}

}

int find(int key, List* list) {
	for (int i = 0; i < list->count; i++)
	{
		if (list->list[i] == key) {
			return i;//找到了,返回下标
		}

	}
	return fail;//都没找到,返回-1
}

//中间插入
void insert_mid(int key, List* list,int data) {
	if (list->count < list->maxSize) {
		int index = find(data, list);//找下标
		if (index == -1) {
			//找不到,没有这个元素,退出吧
		}
		else {
			//先移动位置,先移后面的
			int i;
			for(i = list->count; i > index; i--)//如果死循环,可能会有定义错误的for-loop
			{
				list->list[i] = list->list[i - 1];

			}
			list->list[index] = key;
			list->count++;
		}

	}
	else {
		//提示满了,或者直接扩容
	}

}

void printfList(List*list) {
	for (int i = 0; i < list->count; i++) {//如果死循环,可能会有定义错误的for-loop
		printf("%d ", list->list[i]);
	}
	printf("\n");

}


暂时到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

amojiacoco

请我杯饮料吧

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

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

打赏作者

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

抵扣说明:

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

余额充值