目录
1. 什么是线性表
线性表的分类
2. 什么是顺序表
3.顺序表的分类
3.1 静态顺序表
3.2 动态顺序表
4.顺序表的优缺点
5.模拟实现顺序表的相关结构,即顺序表的操作
SeqList.h文件,声明顺序表的相关结构和函数
SeqList.c文件,定义顺序表的相关函数
6.模拟实现通讯录
test.c文件,用于测试通讯录
Contact.h文件,用于声明通讯录及其相关函数
Contact.c文件,用于实现通讯录函数
在学习之前,我们需要知道我们接下来所学的是数据结构,线性表是一种数据结构,而顺序表是线性表的一种,了解这个,我们就不会搞混下面的讲解了。
那么什么是数据结构呢,即存储和组织数据的一种方式;是指相互之间存在一种或多种特定关系的数据元素集合。上面是一系列“黑话”,我们从实际出发,看看为什么需要数据结构呢?
什么是线性表呢,在生活中其实很常见,我们路过小学,幼儿园总能看见小朋友们排成一列走出校门,第一个小朋友就是排头,最后一个小朋友就是队尾,按顺序排成一队,每一个小朋友都知道他前面是谁,后面是谁,就如同一根线将他们串联起来,这就可以成为线性表
线性表(List), 零个或多个数据元素的有限序列。
强调几个地方,首先线性表是一个序列,也就是说,元素之间是有序的,元素存在多个,第一个元素无前驱,最后一个元素无后继,其他每个元素有且只有一个前驱和后继。其次线性表强调有限的,无线的数列只存在于数学中的概念。
1.1 顺序表
1.2 单链表:其中单链表又分为多种,但我们只需要掌握单链表和双向循环带头链表,不要头大,在之后的文章里,我将会和大家分享单链表的所有内容
线性表的数据存储结构,指的是用一端地址连续的存储单元一次存储线性表的数据结构
顺序表,就是线性表的顺序存储结构。我们可以用以为数组来实现顺序表,但我们要知道数组并不等同于顺序表
//顺序表的结构代码
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity;
}SL;
//将int重命名为 SLDataType,也可以将int改为char double 结构体等不同类型,
//这样我们可以非常方便的操作改变顺序表存储的数据
区分数组长度和线性表长度的区别
1. 数组长度是存放线性表的存储空间的长度,存储分配后这个量一般是不变的
2. 线性表的长度是线性表中的数据元素的个数,量是变化的。
静态顺序表缺陷:使⽤定长数组存储元素空间给少了不够⽤,给多了造成空间浪费
优点: 无需为表中元素之间的逻辑关系而增加而外的存储空间;可以快速存取表中的任意位置的元素
缺点:插入和删除操作需要移动大量元素;当线性表长度变化较大时,难以确定存储空间的容量;造成存储空间的“碎片化”
#pragma once
#include
#include
#include
#include
#include
#include "Contact.h"
typedef struct ContactgInfo SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity;
}SL;
//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
//打印顺序表
void SLPrint(SL* ps);
//头插
void SLPushFront(SL* ps, SLDataType x);
//尾插
void SLPushBack(SL* ps, SLDataType x);
//头删
void SLPopFront(SL* ps);
//尾删
void SLPopBack(SL* ps);
//在任意位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
//在任意位置删除数据
void SLErase(SL* ps, int pos);
//查找数据
bool SLFind(SL* ps, SLDataType x);
#include "SeqList.h"
//顺序表的初始化
void SLInit(SL* ps)
{
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{
if (ps->a)
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
//检查顺序表空间是否足够
void SLCheckCapacity(SL* ps)
{
if (ps->size == ps->capacity)
{
int newcapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);
SLDataType* temp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
if (temp == NULL)
{
perror("realloc");
return;
}
ps->a = temp;
ps->capacity = newcapacity;
}
}
//检查顺序表是否为空
bool SLIsEmpty(SL* ps)
{
assert(ps);
return ps->capacity == 0;
}
//打印顺序表
void SLPrint(SL* ps)
{
for (int i = 0;i < ps->size;i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
//头插
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
for(int i = ps->size;i>0;i--)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[0] = x;
ps->size++;
}
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
//头删
void SLPopFront(SL* ps)
{
assert(ps);
assert(!SLIsEmpty(ps));
for (int i = 0;i < ps->size-1;i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
//尾删
void SLPopBack(SL* ps)
{
assert(ps);
assert(!SLIsEmpty(ps));
ps->size--;
}
//在任意位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(ps >= 0 && ps <= ps->size);
SLCheckCapacity(ps);
for (int i = ps->size;i > pos;i--)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[pos] = x;
ps->size++;
}
//在任意位置删除数据
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(!SLIsEmpty(ps));
assert(pos >= 0 && pos <=ps->size);
for (int i = pos;i < ps->size-1;i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
//查找数据
bool SLFind(SL* ps, SLDataType x)
{
for (int i = 0;i < ps->size;i++)
{
if (strcmp(ps->a[i].name, x.name) == 0)
{
return 1;
}
}
return 0;
}
#include "SeqList.h"
void menu()
{
printf("*************************************************\n");
printf("**********1.添加联系人 2.删除联系人**********\n");
printf("**********3.修改联系人 4.查找联系人**********\n");
printf("**********5.查看联系人 0,退出***************\n");
printf("*************************************************\n");
}
int main()
{
int input = 0;
contact con;
ContactInit(&con);
do
{
menu();
printf("请输入你想要的操作:>");
scanf("%d", &input);
switch (input)
{
case 1:
ContactAdd(&con);
break;
case 2:
ContactDel(&con);
break;
case 3:
ContactModif(&con);
break;
case 4:
ContactFind(&con);
break;
case 5:
ContactShow(&con);
break;
case 0:
break;
default:
printf("操作失败,请重新选择:<\n");
break;
}
}while(input);
ContactDestroy(&con);
return 0;
}
#pragma once
#include "SeqList.h"
#define NAME_MAX 20
#define SEX_MAX 20
#define TEL_MAX 20
#define ADD_MAX 20
typedef struct SeqList contact;
typedef struct ContactgInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tel[TEL_MAX];
char add[ADD_MAX];
}CInfo;
//通讯录的初始化
void ContactInit(contact* pcon);
//通讯录的销毁
void ContactDestroy(contact* pcon);
//添加联系人
void ContactAdd(contact* pcon);
//删除联系人
void ContactDel(contact* pcon);
//修改联系人
void ContactModif(contact* pcon);
//查看联系人
void ContactShow(contact* pcon);
//查找联系人
void ContactFind(contact* pcon);
#include "SeqList.h"
//通讯录的初始化
void ContactInit(contact* pcon)
{
SLInit(pcon);
}
//通讯录的销毁
void ContactDestroy(contact* pcon)
{
SLDestroy(pcon);
}
//添加联系人
void ContactAdd(contact* pcon)
{
CInfo info;
printf("请输入姓名:");
scanf("%s", info.name);
printf("请输入年龄:");
scanf("%d", &info.age);
printf("请输入性别:");
scanf("%s", info.sex);
printf("请输入电话:");
scanf("%s", info.tel);
printf("请输入住址:");
scanf("%s", info.add);
SLPushBack(pcon, info);
}
//删除联系人
int FindByName(contact* pcon, char name[])
{
assert(pcon);
for (int i = 0;i < pcon->size;i++)
{
if (strcmp(pcon->a[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void ContactDel(contact* pcon)
{
char name[NAME_MAX] = { 0 };
printf("请输入要删除人的姓名:");
scanf("%s", name);
int findidex = FindByName(pcon, name);
if (findidex < 0)
{
printf("没有找到要删除人:<\n");
return;
}
SLErase(pcon, findidex);
}
//修改联系人
void ContactModif(contact* pcon)
{
char name[NAME_MAX] = { 0 };
printf("请输入要修改人的姓名:");
scanf("%s", name);
int findidex = FindByName(pcon, name);
if (findidex < 0)
{
printf("没有找到要修改人:<\n");
return;
}
printf("请输入姓名:");
scanf("%s", pcon->a[findidex].name);
printf("请输入年龄:");
scanf("%d", &pcon->a[findidex].age);
printf("请输入性别:");
scanf("%s", pcon->a[findidex].sex);
printf("请输入电话:");
scanf("%s", pcon->a[findidex].tel);
printf("请输入住址:");
scanf("%s", pcon->a[findidex].add);
printf("修改成功:>\n");
}
//查看联系人
void ContactShow(contact* pcon)
{
assert(pcon);
printf("姓名\t年龄\t性别\t电话\t住址\n");
for (int i = 0;i < pcon->size;i++)
{
printf("%s\t%d\t%s\t%s\t%s\n",pcon->a[i].name,
pcon->a[i].age,
pcon->a[i].sex,
pcon->a[i].tel,
pcon->a[i].add);
}
}
//查找联系人
void ContactFind(contact* pcon)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找人的姓名:");
scanf("%s", name);
int findidex = FindByName(pcon, name);
if (findidex < 0)
{
printf("没有找到要查找人:<\n");
return;
}
printf("姓名\t年龄\t性别\t电话\t住址\n");
printf("%s\t%d\t%s\t%s\t%s\n", pcon->a[findidex].name,
pcon->a[findidex].age,
pcon->a[findidex].sex,
pcon->a[findidex].tel,
pcon->a[findidex].add);
}
数据结构: 数据结构学习阶段,对不同数据结构的代码描述以及他们的应用 (gitee.com)