顺序表
顺序表是什么?
顺序表是数据结构课程中我们接触到的第一个结构
如图便是简单的顺序表了。
顺序表的要点:
1.一整块存储空间
2.存储空间中除首元素与尾元素每个元素都有且仅有一个前件与一个后件。
就像一个数组一样,不过C中的数组不可以自由变化长度,而我们定义的顺序表可以。
顺序表实现思想
现在我们知道了顺序表的要点,我们该如何实现呢?
首先我们需要一整块存储空间来存放我们的顺序表
这个好办,我们使用malloc函数来请求一块存储空间不就好了,那么问题来了我们该以怎样的结构作为malloc的参数呢?值得我们好好思索!
笔者使用了C中的结构体来作为顺序表中的节点元素,这是很常见的一种操作,结构体可以存储不同类型的数据,这对与我们的实际应用有极大好处。
那么现在节点元素有了,士兵有了,还要找一个元帅,也即需要管理顺序表,首选当然是指针啦,光有指针也不够,有车没油也跑不动,这就需要辅助参数,在C的数组中我们利用下标来对数组中的元素进行操作,在顺序表中我们依然如此,因此我们还需要当前顺序表内元素的个数,这样我们就可以利用指针与循环对顺序表中任意元素进行操作了。
现在还有最后一个问题假如分配的存储空间用完了怎么办呢?一个杯子装满了水,再加水就会溢出来,这个时候就要换个大杯子了,对于存储空间也是这样,这就需要扩容了,我们使用C中的realloc函数
这样我们就有了一块扩容过的新的内存区域了,而指向这块存储区域首地址的指针依旧是原先我们使用malloc
分配存储区域时返回的那个指针。realloc函数只是将新分配的内存区域连在原先区域的尾巴上。
现在啊,元帅有3个了啊。
1.指向存储空间首地址的指针
2.顺序表的元素个数
3.空间容量大小
那怎么办呢?C的结构体可以帮助我们组合这些元素,由此我们可以创建一个结构体来管理顺序表。
如此一来我们就可以可以实现顺序表了
项目说明
本文将实现一个可以简单存储一个人姓名,年龄,体重的顺序表,并对表进行增,删,查,改等基础操作。
各位读者可自由利用功能函数,编写测试函数。
这是笔者的输出。
顺序表的操作
初始化
//初始化顺序表
void InitList(sqlist * p)
{
//分配内存块
p->lz = (chx *)malloc(MAXSIZE * sizeof(chx));
//判定是否分配内存块
//assert(p->lz != NULL);
printf("%p %d\n", p->lz, sizeof(chx));
//初始当前元素位置
p->size = 0;
p->capacity = MAXSIZE;
}
增
头插法
//头插法
void SqlistPushFront(sqlist * p, chx e)
{
Checkcapacity(p);//判断顺序表是否还有可用空间;
for(int i = p->size - 1; i >= 0; i--)
{
p->lz[i + 1] = p->lz[i];//将每个的位置都后移;
}
p->lz[0] = e;
p->size++;
}
尾插法
//尾插法
void SqlistPushBack(sqlist * p, chx e)
{
Checkcapacity(p);
p->lz[p->size] = e;
p->size++;
}
指定位置插入
//指定位置插入元素
void SqlListInsert(sqlist * p, int cl, chx e)
{
if(p != NULL && cl <= p->size && cl >= 0)
{
Checkcapacity(p);
for(int i = p->size - 1; i >= cl; i--)
{
p->lz[i + 1] = p->lz[i];
}
p->lz[cl] = e;
p->size++;
}
else
{
printf("失败!!!!!!");
exit(1);
}
}
删
头删法
//头删法
void SqlistPopFront(sqlist * p)
{
if(p != NULL && p->size > 0)
{
for(int i = 1; i <= p->size; i++)
{
p->lz[i - 1] = p->lz[i];
}
p->size--;
}
else
{
printf("失败\n");
exit(1);
}
}
尾删法
//尾删法
void SqlistPopBack(sqlist * p)
{
if(p != NULL && p->size > 0)
{
p->lz[p->size - 1] = p->lz[p->size];
p->size--;
}
else
{
printf("失败\n");
exit(1);
}
}
指定位置删除
//指定位置删除元素
void SqlistPop(sqlist * p, int cl, chx e)
{
if(p != NULL && cl <= p->size && cl >= 0)
{
Checkcapacity(p);
for(int i = cl; i <= p->size; i++)
{
p->lz[i - 1] = p->lz[i];
}
p->size--;
}
else
{
printf("失败!!!!!!");
exit(1);
}
}
查
//查找顺序表内容
int SqlistFind(sqlist * p, char * l)
{
int i = 0;
while(i < p->size)
{
if(strcmp(p->lz[i].ch, l) == 0)
{
return i;
}
else
{
i++;
continue;
}
}
printf("未找到元素");
}
改
//改变节点的值
void Sqlistgai(sqlist * p, chx e)
{
//直接将数据域更改
*(p->lz) = e;
}
源代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//分配的最大元素个数
#define MAXSIZE 2
//顺序表的的结构元素
typedef struct
{
char ch[10];
int lx;
float xz;
}chx;
//管理顺序表的结构
typedef struct
{
chx * lz;//基地址
int size;//有效数据个数
int capacity;//空间容量大小
}sqlist;
//初始化数据元素
void InitList(sqlist * p);
//初始化顺序表时读取内容
void Lx1(sqlist * p);
//输出顺序表的内容
void SqlistPut(sqlist * p);
//检查存储空间
void Checkcapacity(sqlist * p);
//头插法
void SqlistPushFront(sqlist * p, chx e);
//尾插法
void SqlistPushBack(sqlist * p, chx e);
//头删法
void SqlistPopFront(sqlist * p);
//尾删法
void SqlistPopBack(sqlist * p);
//指定位置插入
void SqlListInsert(sqlist * p, int cl, chx e);
//指定位置删除
void SqlistPop(sqlist * p, int cl, chx e);
//删除顺序表
void SqlistDel(sqlist * p);
//更改顺序表节点的值
void Sqlistgai(sqlist * p, chx e);
//测试函数1
void L1(sqlist * p);
//测试函数2
void L2(sqlist * p);
//测试函数3
void L3(sqlist * p);
//在顺序表中查找值
int SqlistFind(sqlist * p, char * l);
//主函数
int main(void)
{
sqlist lc;
sqlist * p;
p = &lc;
int i;
char l[10];
InitList(&lc);
Lx1(&lc);
printf("----------------\n");
SqlistPut(&lc);
L1(p);
L3(p);
printf("请输入要查寻的姓名\n");
scanf("%s", l);
//gc();
i = SqlistFind(&lc, l);
printf("%s-%d-%.2f\n", p->lz[i].ch, p->lz[i].lx, p->lz[i].xz);
SqlistPut(&lc);
return 0;
}
//初始化顺序表
void InitList(sqlist * p)
{
//分配内存块
p->lz = (chx *)malloc(MAXSIZE * sizeof(chx));
//判定是否分配内存块
//assert(p->lz != NULL);
printf("%p %d\n", p->lz, sizeof(chx));
//初始当前元素位置
p->size = 0;
p->capacity = MAXSIZE;
}
//扩充空间
void Checkcapacity(sqlist * p)
{
if(p->size == p->capacity)
{
chx * tmp = (chx *)realloc(p->lz, sizeof(chx) * 2 * p->capacity);
if(tmp == NULL)
{
printf("扩充空间失败");
return;
}
else
{
p->lz = tmp;
p->capacity *= 2;
}
}
}
//尾插法
void SqlistPushBack(sqlist * p, chx e)
{
Checkcapacity(p);
p->lz[p->size] = e;
p->size++;
}
//尾删法
void SqlistPopBack(sqlist * p)
{
if(p != NULL && p->size > 0)
{
p->lz[p->size - 1] = p->lz[p->size];
p->size--;
}
else
{
printf("失败\n");
exit(1);
}
}
//头插法
void SqlistPushFront(sqlist * p, chx e)
{
Checkcapacity(p);//判断顺序表是否还有可用空间;
for(int i = p->size - 1; i >= 0; i--)
{
p->lz[i + 1] = p->lz[i];//将每个的位置都后移;
}
p->lz[0] = e;
p->size++;
}
//头删法
void SqlistPopFront(sqlist * p)
{
if(p != NULL && p->size > 0)
{
for(int i = 1; i <= p->size; i++)
{
p->lz[i - 1] = p->lz[i];
}
p->size--;
}
else
{
printf("失败\n");
exit(1);
}
}
//查找顺序表内容
int SqlistFind(sqlist * p, char * l)
{
int i = 0;
while(i < p->size)
{
if(strcmp(p->lz[i].ch, l) == 0)
{
return i;
}
else
{
i++;
continue;
}
}
printf("未找到元素");
}
//指定位置插入元素
void SqlListInsert(sqlist * p, int cl, chx e)
{
if(p != NULL && cl <= p->size && cl >= 0)
{
Checkcapacity(p);
for(int i = p->size - 1; i >= cl; i--)
{
p->lz[i + 1] = p->lz[i];
}
p->lz[cl] = e;
p->size++;
}
else
{
printf("失败!!!!!!");
exit(1);
}
}
//指定位置删除元素
void SqlistPop(sqlist * p, int cl, chx e)
{
if(p != NULL && cl <= p->size && cl >= 0)
{
Checkcapacity(p);
for(int i = cl; i <= p->size; i++)
{
p->lz[i - 1] = p->lz[i];
}
p->size--;
}
else
{
printf("失败!!!!!!");
exit(1);
}
}
//销毁顺序表
void SqlistDel(sqlist * p)
{
if(p != NULL)
{
free(p->lz);
p->lz = NULL;
p->size = p->capacity = 0;
}
else
{
printf("失败!!!!!!");
exit(1);
}
}
//改变节点的值
void Sqlistgai(sqlist * p, chx e)
{
//直接将数据域更改
*(p->lz) = e;
}
//初始化顺序表时读取内容
void Lx1(sqlist * p)
{
char cl;
int k = 0;
printf("请输入姓名,年龄,体重\n");
while(k < p->capacity)
{
scanf("%s %d %f", &p->lz[k].ch, &p->lz[k].lx, &p->lz[k].xz);
while(getchar() != '\n')
{
continue;
}
k += 1;
p->size++;
printf("当前顺序表中元素个数:%d\n",p->size);
if(k < p->capacity)
{
printf("请输入姓名,年龄,体重\n");
}
else
{
printf("输入完成\n");
}
}
}
//输出顺序表存储的内容
void SqlistPut(sqlist * p)
{
int i = 0;
printf("----------------顺序表中存储的内容\n");
while(i < p->size)
{
printf("%s-%d-%.2f\n", p->lz[i].ch, p->lz[i].lx, p->lz[i].xz);
i++;
}
}
//输入元素并尾插入
void L1(sqlist * p)
{
chx e;
Checkcapacity(p);
printf("----------------进行尾插操作\n");
printf("请输入姓名,年龄,体重\n");
scanf("%s %d %f", e.ch, &e.lx, &e.xz);
SqlistPushBack(p, e);
printf("当前顺序表中元素个数:%d\n",p->size);
printf("当前顺序表存储空间大小:%d\n",p->capacity);
}
//尾删除操作
void L2(sqlist * p)
{
Checkcapacity(p);
printf("----------------进行尾删操作\n");
SqlistPopBack(p);
printf("当前顺序表中元素个数:%d\n",p->size);
}
//指定位置插入
void L3(sqlist * p)
{
chx e;
int cl;
Checkcapacity(p);
printf("----------------进行指定位置插入操作\n");
printf("请输入姓名,年龄,体重\n");
scanf("%s %d %f", e.ch, &e.lx, &e.xz);
printf("请输入指定位置\n");
scanf("%d", &cl);
SqlListInsert(p, cl, e);
printf("当前顺序表中元素个数:%d\n",p->size);
printf("当前顺序表存储空间大小:%d\n",p->capacity);
}