文章目录
前言
顺序表的C实现。尽量贴合书上伪代码的形式。
定义
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,这种表示
也称作线性表的顺序存储结构或顺序映像。通常,称这种存储结构的线性表为顺序表(Sequenital List)。
特点
逻辑上相邻的数据元素,其物理次序也是相邻的。
结构示意
约定
1. 常量
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100 //顺序表的最大长度
2. 关键声明和定义
typedef int Status;
typedef char *ElemType; //为了存储姓名,故将其定义为char *
typedef struct
{
ElemType *elem; //存储空间的基地址
int length; //当前长度
} SqList; //顺序表的结构类型
3. 关键函数
3.1 InitList(顺序表的初始化)
Status InitList(SqList *L)
{
L->elem = (ElemType *)calloc(MAXSIZE, sizeof(ElemType)); //为顺序表分配一个大小为MAXSIZE的数组空间
if (!(L->elem))
exit(OVERFLOW); //存储分配失败退出
L->length = 0; //空表长度为0
printf("线性表初始化完成!\n");
return OK;
}
3.2 GetElem(顺序表的取值)
Status GetElem(SqList L, int i, ElemType e)
{
if (i < 1 || i > L.length)
{
return ERROR; //判断i值是否合理
}
strcpy(e, L.elem[i-1]); //由于Elemtype实际为char *, 故使用strcpy进行赋值(这样释放的时候就不会把elem一块释放了)
return OK;
}
3.3 LocateElem(顺序表的查找)
int LocateElem(SqList L, ElemType e)
{
for (size_t i = 0; i < L.length; i++)
{
if (strcmp(L.elem[i], e) == 0) //同上,字符串对比用strcmp
{
return i + 1; //查找成功,返回序号i+1
}
}
return 0; //查找失败,返回0
}
3.4 ListInsert(顺序表的插入)
Status ListInsert(SqList *L, int i, ElemType e)
{
if ((i < 1) || (i > L->length + 1))
return ERROR; //i值不合法
if (L->length == MAXSIZE)
return ERROR; //当前存储空间已满
for (int j = L->length - 1; j >= i - 1; j--)
{
L->elem[j + 1] = L->elem[j]; //插入位置及之后的元素后移
}
L->elem[i - 1] = e; //这里是插入操作,所以直接等号把地址传过去,最后可以直接释放。将新元素e放入第i个位置
++L->length; //表长加一
return OK;
}
3.5 ListDelete(顺序表的删除)
Status ListDelete(SqList *L, int i)
{
if ((i < 1) || i > L->length)
return ERROR; //i值不合法
for (size_t j = i; j <= L->length - 1; j++)
{
L->elem[j - 1] = L->elem[j]; //被删除元素之后的元素前移
}
--L->length; //表长减一
printf("第%d条记录已删除!\n", i);
return OK;
}
一个简单的学生表管理程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100
typedef int Status;
typedef char *ElemType;
typedef struct
{
ElemType *elem;
int length;
} SqList;
Status InitList(SqList *L);
Status GetElem(SqList L, int i, ElemType e);
int get_int(void);
int LocateElem(SqList L, ElemType e);
Status ClearList(SqList *L);
Status ListDelete(SqList *L, int i);
Status DestroyList(SqList *L);
Status ListInsert(SqList *L, int i, ElemType e);
void TraverseList(SqList L);
void menu(void);
int main(int argc, char const *argv[])
{
SqList S;
SqList *L = &S;
char ch = 0;
char * find;
int check = 1, no = 0, index = 0;
menu();
while ((ch = getchar()) != 'q')
{
fflush(stdin);
if (ch == 'a')
{
InitList(L);
menu();
}
if (ch == 'b')
{
char * temp = (char *)malloc(sizeof(char) * 51);
printf("输入插入的姓名(空行回车结束):");
while (fgets(temp, 51, stdin) != NULL && temp[0] != '\n')
{
find = strchr(temp, '\n');
if (find)
{
*find = '\0';
}
printf("输入插入的位置(从1到%d):", S.length+1);
while (scanf("%d", &index) != 1)
{
printf("请输入数字!\n");
}
ElemType in = (ElemType)malloc(sizeof(char) * 51);
strcpy(in, temp);
fflush(stdin);
if (ListInsert(L, index, in) == ERROR)
{
printf("请输入范围内的数字!(1到%d)\n", S.length+1);
}
printf("输入插入的姓名(空行回车结束):");
}
free(temp);
printf("插入后顺序表的内容:\n");
TraverseList(S);
menu();
}
if (ch == 'c')
{
char * temp = (char *)malloc(sizeof(char) * 51);
ElemType se = (ElemType)malloc(sizeof(char) * 51);
printf("输入查找的姓名(空行回车结束):");
while (fgets(temp, 51, stdin) != NULL && temp[0] != '\n')
{
find = strchr(temp, '\n');
if (find)
{
*find = '\0';
}
strcpy(se, temp);
no = LocateElem(S, se);
if (no == 0)
{
printf("未找到符合条件的位置!\n");
printf("输入查找的姓名(空行回车结束):");
continue;
}
printf("第一个符合条件的位置: %d\n", no);
printf("输入查找的姓名(空行回车结束):");
}
free(temp);
free(se);
menu();
}
if (ch == 'd')
{
int n = 1;
ElemType ge = (ElemType)malloc(sizeof(char) * 51);
printf("输入查找的位置(0结束):");
while (1)
{
n = get_int();
if (n == 0)
{
break;
}
if (GetElem(S, n, ge) == ERROR)
{
printf("请输入范围内的数字!(1到%d)\n", S.length+1);
}
printf("第一个符合条件的位置的内容:%s\n", ge);
printf("输入查找的位置(0结束):");
}
menu();
}
if (ch == 'e')
{
printf("遍历顺序表:\n");
TraverseList(S);
menu();
}
if (ch == 'f')
{
int n = 1;
ElemType de = (ElemType)malloc(sizeof(char) * 51);
printf("输入删除的位置(0结束):");
while (1)
{
n = get_int();
if (n == 0)
{
break;
}
if (ListDelete(L, n) == ERROR)
{
printf("请输入范围内的数字!(1到%d)\n", S.length+1);
}
printf("输入删除的位置(0结束):");
}
printf("删除完成后的顺序表:\n");
TraverseList(S);
menu();
}
if (ch == 'g')
{
ClearList(L);
TraverseList(S);
menu();
}
if (ch == 'h')
{
DestroyList(L);
menu();
}
}
return 0;
}
Status InitList(SqList *L)
{
L->elem = (ElemType *)calloc(MAXSIZE, sizeof(ElemType));
if (!(L->elem))
exit(OVERFLOW);
L->length = 0;
printf("线性表初始化完成!\n");
return OK;
}
Status GetElem(SqList L, int i, ElemType e)
{
if (i < 1 || i > L.length)
{
return ERROR;
}
strcpy(e, L.elem[i-1]);
return OK;
}
int LocateElem(SqList L, ElemType e)
{
for (size_t i = 0; i < L.length; i++)
{
if (strcmp(L.elem[i], e) == 0)
{
return i + 1;
}
}
return 0;
}
Status DestroyList(SqList *L)
{
ClearList(L);
free(L->elem);
printf("线性表已销毁!\n");
return OK;
}
Status ListInsert(SqList *L, int i, ElemType e)
{
if ((i < 1) || (i > L->length + 1))
return ERROR;
if (L->length == MAXSIZE)
return ERROR;
for (int j = L->length - 1; j >= i - 1; j--)
{
L->elem[j + 1] = L->elem[j];
}
L->elem[i - 1] = e;
++L->length;
return OK;
}
Status ClearList(SqList *L)
{
if (!(L->elem))
return ERROR;
for (size_t i = 0; i < MAXSIZE; i++)
{
L->elem[i] = 0;
}
L->length = 0;
printf("线性表已清空!\n");
return OK;
}
void TraverseList(SqList L)
{
printf("序号 姓名\n");
for (size_t i = 0; i < L.length; i++)
{
printf("%d %s\n", i + 1, L.elem[i]);
}
}
Status ListDelete(SqList *L, int i)
{
if ((i < 1) || i > L->length)
return ERROR;
for (size_t j = i; j <= L->length - 1; j++)
{
L->elem[j - 1] = L->elem[j];
}
--L->length;
printf("第%d条记录已删除!\n", i);
return OK;
}
int get_int(void)
{
int input;
char ch;
while (scanf("%d", &input) != 1)
{
while ((ch = getchar()) != '\n')
{
;
}
printf("请输入数字!\n");
}
return input;
}
void menu()
{
printf("线性表的顺序表示与实现:\n");
printf("a.顺序表初始化\n");
printf("b.顺序表的插入\n");
printf("c.顺序表的查找\n");
printf("d.顺序表的取值\n");
printf("e.顺序表的遍历\n");
printf("f.顺序表的删除\n");
printf("g.顺序表的清空\n");
printf("h.顺序表的销毁\n");
printf("q.退出\n");
printf("a/b/c/d/e/f/g/h/q:");
}