什么是顺序表?所谓顺序表,是指表中的元素一个接一个的在内存中连续存储。说白了,就是数组。但与数组区别不同的是,数组一旦定义了,其长度就固定不变(因为是静态分配内存的,即是在栈内存分配的),而顺序表却不是这样的,它是可以变的(因为是动态分配内存的,即是在堆内存分配的)。本质上,都是连续存储的。但顺序表有缺点——插入和删除。是比较麻烦的,时间复杂度为O(n)。插入一个元素时,其后面的元素都要往后移一位;删除一个元素时,其后面的元素都要往前移一位。因此,为了解决这个问题,又提出来了链式存储结构——链表。后面我们在来介绍它。
下面实现一个简单是顺序表。创建一个线性表,然后遍历输出,在删除某一个元素,若输入一个非数字则终止程序。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <errno.h>
#ifndef DATATYPE
#define DATATYPE int
#endif
typedef DATATYPE datatype;
//定义顺序表逻辑结构
typedef struct seqlist
{
datatype size; // 表的总大小
datatype *data; // 在堆内分配空间,其实是个匿名数组
datatype current; // 当前位置
}seqlist;
// 初始化顺序表
seqlist *init_list(datatype size)
{
seqlist *sq = (seqlist *)malloc(sizeof(seqlist));
if(NULL == sq)
{
printf("malloc error: %s\n", strerror(errno));
return NULL;
}
sq->size = size;
sq->current = -1;
sq->data = (datatype *)calloc(size, sizeof(datatype));
if(NULL == sq->data)
{
printf("malloc error: %s\n", strerror(errno));
free(sq);
return NULL;
}
return sq;
}
// 判空
bool is_empty(seqlist *sl)
{
return sl->current == -1;
}
// 判满
bool is_full(seqlist *sl)
{
return sl->current >= sl->size-1;
}
// 添加
bool list_add(seqlist *sl, datatype data)
{
if(is_full(sl))
return false;
sl->current++;
sl->data[sl->current] = data;
return true;
}
// 删除元素
bool list_del(seqlist *sl, datatype val)
{
if(is_empty(sl))
return false;
datatype i;
for(i=0; i<sl->current; i++)
{
if(sl->data[i] == val)
break;
}
if(i > sl->current)
return false;
while(i < sl->current)
{
sl->data[i] = sl->data[i+1];
i++;
}
sl->current--;
return true;
}
// 遍历输出
void traverse_seqlist(seqlist *sl)
{
if(is_empty(sl))
return;
printf("当前顺序表总共有: %d 个元素\n", sl->current+1);
datatype i;
for(i=0; i<=sl->current; i++)
{
printf("%d\t", sl->data[i]);
}
printf("\n");
}
int main(void)
{
// 1.初始化顺序表
seqlist *sl = init_list(20);
datatype i;
bool rtval;
srand(time(NULL));
// 2.插入5个整数
for(i=0; i<5; i++)
{
/*
if(!list_add(sl, rand()%100))
{
printf("已经满了!\n");
break;
}
*/
rtval = list_add(sl, rand()%100);
if(rtval == false)
{
printf("已经满了!\n");
break;
}
}
// 3.遍历输出
traverse_seqlist(sl);
datatype val;
// 4.删除某个节点
while(1)
{
if(is_empty(sl))
{
printf("顺序表为空!\n");
break;
}
printf("请输入你要删除的数字:");
if(scanf("%d", &val) != 1) // 输入非数字退出循环
break;
if(list_del(sl, val))
{
traverse_seqlist(sl);
}
else
{
printf("删除失败,请重新输入!\n");
}
}
return 0;
}