读者须知:本文章仅做为博主的笔记,抛砖引玉,代码实现上不完全,也无法完全考虑各种要素,有时间会补充。
注:博主大一新生,请多指教。
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");
}
暂时到这里。
&spm=1001.2101.3001.5002&articleId=127787682&d=1&t=3&u=de533182f64944269749ca0675b576bd)
6794

被折叠的 条评论
为什么被折叠?



