目录
什么是线性表?
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结 构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物 理上存储时,通常以数组和链式结构的形式存储。
今天我们主要介绍顺序表。
顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组 上完成数据的增删查改。
顺序表分为静态顺序表和动态顺序表
静态顺序表
静态顺序表:使用定长数组存储元素。
//顺序表的静态存储
#define N 7
typedef int SLDataType;
typedef struct SeqList
{
SLDataType array[N];//定长数组
size_t size; //有效数据的个数
}SeqList;
静态顺序表就是事先就开辟好一定大小的数组空间,通过修改程序中的宏定义N的值,来改变数组的大小。其实也就是我们平时用的数组。不过是通过结构体的方式再现。
下面我着重介绍一下动态顺序表。
动态顺序表
动态顺序表:使用动态开辟的数组存储。
//顺序表的动态存储
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* array; //指向动态开辟的数组
size_t size; //有效数据的个数
size_t capicity; //容量空间的大小
}SeqList;
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪 费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。
typedef int SLDataType;
struct SeqList
{
SLDataType* data;
unsigned size;
unsigned capacity;
};
// 对数据的管理:增删查改
//检查空间,空间满了就增加空间
void SeqCheckAdd(struct SeqList* ps);
//顺序表的初始化
void SeqListInit(struct SeqList* ps);
//顺序表的销毁
void SeqListDestory(struct SeqList* ps);
//打印顺序表
void SeqListPrint(struct SeqList* ps);
//尾插
void SeqListPushBack(struct SeqList* ps, SLDataType x);
//头插
void SeqListPushFront(struct SeqList* ps, SLDataType x);
//头删
void SeqListPopFront(struct SeqList* ps);
//尾删
void SeqListPopBack(struct SeqList* ps);
// 顺序表查找
int SeqListFind(struct SeqList* ps, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(struct SeqList* ps, size_t pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(struct SeqList* ps, size_t pos);
SeqListInit函数将结构体变量的成员初始化。指针data指向NULL,成员size和capacity等于0;
SeqCheckAdd函数是用来检查顺序表空间的。要是顺序表还没有开辟空间,就先开辟四个SLDataType大小的空间,若顺序表已经开辟过空间,那就检查size是否等于capacity,即当前数据个数是否已经达到顺序表的上限,使用realloc开辟空间。
顺序表的其他功能就不一一介绍了,因为顺序表除了动态开辟空间以外,和数组没什么太大区别。
下面我把动态顺序表的代码贴在下面。
text.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
//顺序表的增删查改
enum
{
Destory,
PushBack,
PushFront,
PopBack,
PopFront,
ListFind,
ListInsert,
ListErase,
ListPrint
};
void menu()
{
printf("****1、PushBack 2、PushFront****\n");
printf("****3、PopBack 4、PopFront ****\n");
printf("****5、ListFind 6、ListInsert***\n");
printf("****7、ListErase 8、ListPrint****\n");
printf("****0、Destory ****\n");
}
int main()
{
int input = 0;
int x = 0;
int pos;
struct SeqList ps;
SeqListInit(&ps);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case PushBack:
printf("请输入要添加的数字:>");
scanf("%d", &x);
SeqListPushBack(&ps, x);
break;
case PushFront:
printf("请输入要添加的数字:>");
scanf("%d", &x);
SeqListPushFront(&ps, x);
break;
case PopBack:
SeqListPopBack(&ps);
break;
case PopFront:
SeqListPopFront(&ps);
break;
case ListFind:
printf("请输入要查找的数字:>");
scanf("%d", &x);
if (SeqListFind(&ps, x) != 0)
{
printf("找到了,位置是%d\n", SeqListFind(&ps, x) + 1);
}
else
{
printf("没找到!");
}
break;
case ListInsert:
printf("请输入位置:>");
scanf("%d", &pos);
printf("请输入要添加的数字:>");
scanf("%d", &x);
SeqListInsert(&ps, pos, x);
break;
case ListErase:
printf("请输入位置:>");
scanf("%d", &pos);
SeqListErase(&ps, pos);
break;
case ListPrint:
SeqListPrint(&ps);
break;
case Destory:
SeqListDestory(&ps);
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}
Seqlist.h
typedef int SLDataType;
struct SeqList
{
SLDataType* data;
unsigned size;
unsigned capacity;
};
// 对数据的管理:增删查改
void SeqCheckAdd(struct SeqList* ps);
void SeqListInit(struct SeqList* ps);
void SeqListDestory(struct SeqList* ps);
void SeqListPrint(struct SeqList* ps);
void SeqListPushBack(struct SeqList* ps, SLDataType x);
void SeqListPushFront(struct SeqList* ps, SLDataType x);
void SeqListPopFront(struct SeqList* ps);
void SeqListPopBack(struct SeqList* ps);
// 顺序表查找
int SeqListFind(struct SeqList* ps, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(struct SeqList* ps, size_t pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(struct SeqList* ps, size_t pos);
Seqlist.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void SeqCheckAdd(struct SeqList* ps)
{
if (ps->size == ps->capacity)
{
int newcapacity = (ps->capacity == 0) ? 4 : 2 * ps->capacity;
int* newdata = realloc(ps->data, sizeof(SLDataType) * newcapacity);
if (newdata == NULL)
{
perror("realloc Failed");
return;
}
ps->data = newdata;
ps->capacity = newcapacity;
}
}
//初始化顺序表
void SeqListInit(struct SeqList* ps)
{
ps->data = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SeqListDestory(struct SeqList* ps)
{
ps->data = 0;
ps->capacity = 0;
free(ps->data);
ps->data = NULL;
}
void SeqListPrint(struct SeqList* ps)
{
unsigned i = 0;
for (i = 0; i < (ps->size); i++)
{
printf("%d ", ps->data[i]);
}
printf("\n");
}
void SeqListPushBack(struct SeqList* ps, SLDataType x)
{
SeqCheckAdd(ps);
ps->data[ps->size] = x;
ps->size++;
}
void SeqListPushFront(struct SeqList* ps, SLDataType x)
{
SeqCheckAdd(ps);
unsigned i = 0;
for (i = 0; i < ps->size; i++)
{
ps->data[ps->size - i] = ps->data[ps->size - 1 - i];
}
ps->data[0] = x;
ps->size++;
}
void SeqListPopFront(struct SeqList* ps)
{
unsigned i = 0;
if (ps->size == 0)
{
printf("Pop Front Failed!\n");
}
else
{
for (i = 0; i < ps->size - 1; i++)
{
ps->data[i] = ps->data[i + 1];
}
ps->size--;
}
}
void SeqListPopBack(struct SeqList* ps)
{
if (ps->size == 0)
{
printf("Pop Back Failed!\n");
}
else
{
ps->size--;
}
}
// 顺序表查找
int SeqListFind(struct SeqList* ps, SLDataType x)
{
unsigned i = 0;
for (i = 0; i < ps->size; i++)
{
if (ps->data[i] == x)
{
return i;
}
}
return 0;
}
// 顺序表在pos位置插入x
void SeqListInsert(struct SeqList* ps, size_t pos, SLDataType x)
{
if (pos<1 || pos>ps->size + 1)
{
printf("List Insert Failed!\n");
}
else
{
SeqCheckAdd(ps);
unsigned i = 0;
for (i = 0; i < ps->size - pos + 1; i++)
{
ps->data[ps->size - i] = ps->data[ps->size - 1 - i];
}
ps->data[pos - 1] = x;
ps->size++;
}
}
// 顺序表删除pos位置的值
void SeqListErase(struct SeqList* ps, size_t pos)
{
if (pos<1 || pos>ps->size)
{
printf("List Erase Failed!\n");
}
else
{
unsigned i = 0;
for (i = 0; i < ps->size - pos; i++)
{
ps->data[pos - 1 + i] = ps->data[pos + i];
}
ps->size--;
}
}