线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。
线性表的顺序存储结构是一种随机存取的存储结构
文章目录
实现的功能(严蔚敏数据结构19页的基本操作实现)
线性表的动态分配顺序存储结构与准备
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h`
#include<malloc.h>
#define TRUE 1 //代码中出现TRUE相当于出现了1
#define FALSE 0 //出现FALSE相当于出现了0
#define OK 1 //出现OK相当于出现了1
#define ERROR 0 //出现ERROR相当于出现了0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct {
ElemType* elem; //存储空间的基址
int length; //当前线性表的长度
int listsize; //当前线性表的存储容量
}SqList;
构造空的线性表
Status InList_Sq(SqList* L) {
L->elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType)); //L.elem为首元素的地址
if (!L->elem) { //如果存储空间分配失败,L.elem为NULL
printf("存储空间分配失败\n");
exit(OVERFLOW);
}
L->length = 0; //当前线性表为空表,即线性表长度为0
L->listsize = LIST_INIT_SIZE; //给线性表分配初始容量
printf("一个空的线性表已经构建成功\n"); //输出空线性表构建成功的提示消息
return OK;
}
对线性表进行赋值
Status ValueList_Sq(SqList* L)
{
int i, j;
printf("请输入线性表元素个数:");
scanf("%d", &i);
while (i > L->listsize) //如果所需元素个数大于内存大小是一直开辟新空间直到可以容纳
{
L->elem = realloc(L->elem, LIST_INIT_SIZE * sizeof(ElemType)); //realloc函数重新分配空间
L->listsize += LIST_INIT_SIZE;
}
for (j = 0; j < i; j++)
{
printf("请输入第%d个元素:", j + 1);
scanf("%d", &L->elem[j]);
}
printf("线性表已构造成功\n");
L->length = i;
return OK;
}
对线性表进行销毁
Status DistoryList_Sq(SqList* L)
{
if (!L->elem) //判断线性表是否为空,若首地址存在则说明不为空
{
printf("请先建立线性表");
return ERROR;
}
free(L->elem);
L->length = 0;
L->listsize = 0;
printf("已销毁");
return OK;
}
将线性表重置为空表
Status ClearList_Sq(SqList* L)
{
if (L->elem)
{
L->length = 0;
return OK;
}
else
printf("线性表不存在");
return OK;
}
判断线性表是否为空
Status ListEmpty_Sq(SqList L)
{
if (L.elem)
{
if (L.length != 0)
{
printf("线性表不是空表\n");
return FALSE;
}
else
{
printf("线性表是空表\n");
return TRUE;
}
}
else
{
printf("线性表不存在无法判断\n");
return OK;
}
}
获取线性表中的元素个数(获取长度)
Status ListLength_Sq(SqList L)
{
if (L.elem)
{
int k;
k = L.length;
printf("线性表的长度为%d\n", k);
return k;
}
else
{
printf("线性表不存在");
return OK;
}
}
用e返回L中第i个数据元素的值
Status GetElem_Sq(SqList L, int i,ElemType* e)
{
if (L.elem)
{
if (i<1 || i>L.length)
{
printf("请输入一个有效数字:\n");
return ERROR;
}
else
{
*e = L.elem[i - 1]; //数据元素的下标从0开始
printf("第%d个位置的元素为%d\n", index, num);
}
return OK;
}
else
printf("线性表不存在\n");
return OK;
}
返回L中第一个与e满足compare()的数据元素的位序
Status LocateElem_Sq(SqList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
ElemType* p;
if (L.elem)
{
int i = 1;
p = L.elem;
while (i <= L.length && !(*compare)(*p++, e))
i++;
if (i <= L.length)
{
printf("与e满足compare的次序是%d\n", i);
return OK;
}
else
return 0;
}
else
return OK;
}
compare函数原型
Status compare(ElemType a, ElemType b)
{
if (a == b)
return TRUE;
else
return FALSE;
}
返回cure_e元素的直接前驱
线性表中第一个元素没有前驱所以直接从第二个元素开始即i = 2
Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e)
{
int i = 2;
ElemType* p = L.elem + 1;
while (i <= L.length && *p != cur_e)
{
p++;
i++;
}
if (i > L.length)
return INFEASIBLE;
else
{
*pre_e = *--p;
printf("%d的前驱是%d\n", cur_e, *pre_e);
return OK;
}
}
返回cure_e元素的直接后继
线性表中的最后一个元素没有直接后继所以循环条件为i < L.length(线性表长度)终止条件为i = L.length
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e)
{
if (L.elem)
{
int i = 1;
ElemType* p = L.elem;
while (i < L.length && *p != cur_e)
{
i++;
p++;
}
if (i == L.length)
return INFEASIBLE;
else
{
*next_e = *++p;
printf("%d的后继是%d\n", cur_e, *next_e);
return OK;
}
}
else
printf("线性表不存在");
return OK;
}
在线性表的i位置插入数据元素e
如果线性表长度等于当前线性表存储容量还是要realloc增加线性表的存储容量
插入元素的话,插入位置后的元素都要向后移动一位。
Status ListInsert_Sq(SqList* L, int i, ElemType e)
{
ElemType* newbase;
ElemType* p, * q;
if (i<1 || i>L->length)
return ERROR;
if (L->length >= L->listsize)
{
newbase = (ElemType*)realloc(L->elem, (L->listsize + LIST_INIT_SIZE) * sizeof(ElemType));
if (!newbase)
{
printf("空间不足");
exit(EXIT_FAILURE);
}
else
{
L->elem = newbase;
L->listsize += LIST_INIT_SIZE;
}
}
q = &L->elem[i - 1];//q为当前插入位置
for (p = (&L->elem[L->length - 1]); p >= q; p--)//p为线性表末尾元素位置
*(p + 1) = *p; //插入位置后元素均向后移动一位
*q = e;
L->length += 1;
return OK;
}
删除线性表中第i个位置的元素
与插入类似,插入时均向后移一位,删除时均向前移一位
Status DeleteList_Sq(SqList* L, int i)
{
ElemType* p, * q;
if (i<1 || i>L->length)
return ERROR;
p = L->elem + i - 1; 。//要删除元素
q = L->elem + L->length - 1; //表尾元素
for (++p; p <= q; p++)
*(p - 1) = *p; //均向前移一位
L->length -= 1;
return OK;
}
依次对线性表的每个数据元素调用vi函数
vs环境下`
Status ListTraverse(SqList L, void(*vi)(ElemType*))
{
ElemType* p;
int i;
p = L.elem;
for (i = 1; i <= L.length; i++)
vi(p++);
printf("\n");
return OK;
}
vi函数 遍历函数
void vi(ElemType* p)
{
printf("%d ", *p);
}
测试函数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
//函数结果状态字符
#define TRUE 1 //代码中出现TRUE相当于出现了1
#define FALSE 0 //出现FALSE相当于出现了0
#define OK 1 //出现OK相当于出现了1
#define ERROR 0 //出现ERROR相当于出现了0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct {
ElemType* elem; //存储空间的基址
int length; //当前线性表的长度
int listsize; //当前线性表的存储容量
}SqList;
Status InList_Sq(SqList* L); //构造空的线性表
Status ValueList_Sq(SqList* L); //对线性表进行赋值
Status DistoryList_Sq(SqList* L); //对线性表进行销毁
Status ClearList_Sq(SqList* L); //对线性表进行重置
Status ListEmpty_Sq(SqList L); //判断线性表是否为空
Status ListLength_Sq(SqList L); //获取线性表元素个数
Status GetElem_Sq(SqList L, int index); //获取线性表某一位置对应的元素
//返回L中第一个与e满足compare()数组元素的位序
Status LocateElem_Sq(SqList L, ElemType e, Status(*compare)(ElemType, ElemType));
Status compare(ElemType a, ElemType b); //compare函数
//cur_e是L的数据元素,用pre_e返回他的直接前驱
Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e);
//cur_e是L的数据元素,用next_e返回它的直接后继
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e);
//在线性表第i个位置前插入新的数据元素,L长度+1
Status ListInsert_Sq(SqList* L, int i, ElemType e);
//删除线性表某一位置的元素
Status DeleteList_Sq(SqList* L, int i);
//依次对顺序线性表L的每个数据元素调用函数vi()
Status ListTraverse(SqList L, void(*vi)(ElemType*));
void vi (ElemType* p); //打印函数
int main()
{
SqList L; ElemType next = 0, pre = 0;
ElemType cur_e;
int choose, index, e;
while (1) {
printf("*****************************************\n");
printf("* *\n");
printf("* 线性表的顺序表示和实现: *\n");
printf("* *\n");
printf("* 1. 构造一个空的线性表 *\n");
printf("* 2. 对线性表进行赋值 *\n");
printf("* 3. 对线性表进行销毁 *\n");
printf("* 4. 对线性表进行重置 *\n");
printf("* 5. 判断线性表是否为空 *\n");
printf("* 6. 获取线性表的长度 *\n");
printf("* 7. 获取线性表某一位置对应的元素 *\n");
printf("* 8. 返回第一个与e满足compare函数 *\n");
printf("* 9. 求线性表某一元素的前驱 *\n");
printf("* 10. 求线性表某一元素的后继 *\n");
printf("* 11. 在线性表某一位置插入元素 *\n");
printf("* 12. 删除线性表某一位置的元素 *\n");
printf("* 13. 打印线性表 *\n");
printf("* 14. 退出 *\n");
printf("* *\n");
printf("*****************************************\n");
printf("请做出您的选择:");
scanf("%d", &choose);
switch (choose)
{
case 1:InList_Sq(&L); break;
case 2:ValueList_Sq(&L); break;
case 3:DistoryList_Sq(&L); break;
case 4:ClearList_Sq(&L); break;
case 5:ListEmpty_Sq(L); break;
case 6:ListLength_Sq(L); break;
case 7: {
printf("请输入要获取元素的位置:");
scanf("%d", &index);
GetElem_Sq(L, index);
}
break;
case 8: {
printf("请输入e:");
scanf("%d", &e);
LocateElem_Sq(L, e, compare);
}
break;
case 9: {
printf("请输入要查找哪一个元素的前驱:");
scanf("%d", &cur_e);
PriorElem(L, cur_e, &pre);
}
break;
case 10: {
printf("请输入要查找哪一个元素的后继:");
scanf("%d", &cur_e);
NextElem(L, cur_e, &next);
}
break;
case 11: {
printf("请输入插入的位置和插入的元素:");
scanf("%d %d", &index, &e);
ListInsert_Sq(&L, index, e);
}
break;
case 12: {
printf("请输入删除元素的位置:");
scanf("%d", &index);
DeleteList_Sq(&L, index);
}
break;
case 13: ListTraverse(L, vi);
break;
case 14: exit(0);
}
}
return 0;
}
Status InList_Sq(SqList* L) {
L->elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType)); //L.elem为首元素的地址
if (!L->elem) { //如果存储空间分配失败,L.elem为NULL
printf("存储空间分配失败\n");
exit(OVERFLOW);
}
L->length = 0; //当前线性表为空表,即线性表长度为0
L->listsize = LIST_INIT_SIZE; //给线性表分配初始容量
printf("一个空的线性表已经构建成功\n"); //输出空线性表构建成功的提示消息
return OK;
}
Status ValueList_Sq(SqList* L)
{
int i, j;
printf("请输入线性表元素个数:");
scanf("%d", &i);
while (i > L->listsize) //如果所需元素个数大于内存大小是一直开辟新空间直到可以容纳
{
L->elem = realloc(L->elem, LIST_INIT_SIZE * sizeof(ElemType));
L->listsize += LIST_INIT_SIZE;
}
for (j = 0; j < i; j++)
{
printf("请输入第%d个元素:", j + 1);
scanf("%d", &L->elem[j]);
}
printf("线性表已构造成功\n");
L->length = i;
return OK;
}
Status DistoryList_Sq(SqList* L)
{
if (!L->elem) //判断线性表是否为空,若首地址存在则说明不为空
{
printf("请先建立线性表");
return ERROR;
}
free(L->elem);
L->length = 0;
L->listsize = 0;
return OK;
}
Status ClearList_Sq(SqList* L)
{
if (L->elem)
{
L->length = 0;
return OK;
}
else
printf("线性表不存在");
return OK;
}
Status ListEmpty_Sq(SqList L)
{
if (L.elem)
{
if (L.length != 0)
{
printf("线性表不是空表\n");
return FALSE;
}
else
{
printf("线性表是空表\n");
return TRUE;
}
}
else
{
printf("线性表不存在无法判断\n");
return OK;
}
}
Status ListLength_Sq(SqList L)
{
if (L.elem)
{
int k;
k = L.length;
printf("线性表的长度为%d\n", k);
return OK;
}
else
{
printf("线性表不存在");
return OK;
}
}
Status GetElem_Sq(SqList L, int index)
{
int num;
if (L.elem)
{
if (index<1 || index>L.length)
{
printf("请输入一个有效数字:\n");
return ERROR;
}
else
{
num = L.elem[index - 1];
printf("第%d个位置的元素为%d\n", index, num);
}
return OK;
}
else
printf("线性表不存在\n");
return OK;
}
Status LocateElem_Sq(SqList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
ElemType* p;
if (L.elem)
{
int i = 1;
p = L.elem;
while (i <= L.length && !(*compare)(*p++, e))
i++;
if (i <= L.length)
{
printf("与e满足compare的次序是%d\n", i);
return OK;
}
else
return 0;
}
else
return OK;
}
Status compare(ElemType a, ElemType b)
{
if (a == b)
return TRUE;
else
return FALSE;
}
Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e)
{
int i = 2;
ElemType* p = L.elem + 1;
while (i <= L.length && *p != cur_e)
{
p++;
i++;
}
if (i > L.length)
return INFEASIBLE;
else
{
*pre_e = *--p;
printf("%d的前驱是%d\n", cur_e, *pre_e);
return OK;
}
}
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e)
{
if (L.elem)
{
int i = 1;
ElemType* p = L.elem;
while (i < L.length && *p != cur_e)
{
i++;
p++;
}
if (i == L.length)
return INFEASIBLE;
else
{
*next_e = *++p;
printf("%d的后继是%d\n", cur_e, *next_e);
return OK;
}
}
else
printf("线性表不存在");
return OK;
}
Status ListInsert_Sq(SqList* L, int i, ElemType e)
{
ElemType* newbase;
ElemType* p, * q;
if (i<1 || i>L->length)
return ERROR;
if (L->length >= L->listsize)
{
newbase = (ElemType*)realloc(L->elem, (L->listsize + LIST_INIT_SIZE) * sizeof(ElemType));
if (!newbase)
{
printf("空间不足");
exit(EXIT_FAILURE);
}
else
{
L->elem = newbase;
L->listsize += LIST_INIT_SIZE;
}
}
q = &L->elem[i - 1];
for (p = (&L->elem[L->length - 1]); p >= q; p--)
*(p + 1) = *p;
*q = e;
L->length += 1;
return OK;
}
Status DeleteList_Sq(SqList* L, int i)
{
ElemType* p, * q;
if (i<1 || i>L->length)
return ERROR;
p = L->elem + i - 1;
q = L->elem + L->length - 1;
for (++p; p <= q; p++)
*(p - 1) = *p;
L->length -= 1;
return OK;
}
Status ListTraverse(SqList L, void(*vi)(ElemType*))
{
ElemType* p;
int i;
p = L.elem;
for (i = 1; i <= L.length; i++)
vi(p++);
printf("\n");
return OK;
}
void vi(ElemType* p)
{
printf("%d ", *p);
}