前言
顺序表存储结构容易实现随机存取线性表的第i个数据元素的操作,但在插入或删除操作时要移动大量的数据元素,适合数据相对稳定的线性表。
提示:以下是顺序表的基本操作和实现代码,下面案例可供参考
1.头文件
代码如下(示例):
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define FALSE 0
#define TRUE 1
#define ERROR 0
#define OK 1
//线性表的存储空间length初始分配量
#define LIST_INIT_SIZE 10
//线性表的存储空间的分配增加量(防止溢出)
#define LIST_INCREASE 2
//elem是单词element(元素)的缩写,在程序定义中代表某一不确定的类型,也就是抽象的数据类型
#define ElemType int
// Status 是函数的类型,其值是函数的返回结果,如OK等
typedef int Status;
struct Sqlist {
ElemType* data;
int length;//当前长度
int list_size;//当前分配的存储容量
};
2.调用函数
//输出c
void Print(ElemType &c)
{
printf("%d ", c);
}
//compare比较函数,符合条件
Status Compare(ElemType num1, ElemType num2)
{
if (num1 == num2)
return TRUE;
else
return FALSE;
}
3.基本操作函数
代码如下(示例):
//初始化线性表
void InitList(Sqlist& L)
{
//malloc函数申请存储空间
L.data = (ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if (!L.data)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
L.length = 0;
L.list_size = LIST_INIT_SIZE;//初始化存储容量
}
//销毁线性表
void DestoryList(Sqlist& L)
{
free(L.data);//释放L.data所指的存储空间
L.data = NULL;//L.data不再指向任何存储单元
L.length = 0;
L.list_size = 0;
}
//清空线性表,将L重置为空表
void ClearList(Sqlist& L)
{
L.length = 0;
}
//输出线性表的长度
Status ListLength(Sqlist L)
{
return L.length;
}
//若L存在,返回TRUE;否则返回FALSE
Status ListEmpty(Sqlist L)
{
if (L.length == 0)
return TRUE;
else
return FALSE;
}
//用e作为载体返回L中的第i个元素
Status GetData(Sqlist L, int i, ElemType &e)
{
if (i<0 || i>L.length)
return ERROR;
e = *(L.data + i - 1);
return e;
}
//找到第一个与e满足compare()的值的位置,返回其所在的位置
Status LocateData(Sqlist L, ElemType e, Status(*compare)(ElemType, ElemType))
{
int i = 1;
ElemType* p = L.data;
while (i <= L.length && !compare(*p++, e))
i++;
if (i <= L.length)
return i;
else
return 0;
}
//cur_e:线性表的值,pre_e:cur_e前驱
Status PriorData(Sqlist L, ElemType cur_e, ElemType& pre_e)
{
int i = 2;
ElemType* p = L.data + 1;
while (i <= L.length && *p != cur_e)
{
i++;
p++;
}
pre_e = *--p;
if (i <= L.length)
return pre_e;
else
return ERROR;
}
//next_e:所给元素cur_e的后继
Status NextData(Sqlist L, ElemType cur_e, ElemType& next_e)
{
int i = 1;
ElemType* p = L.data;
while (i < L.length && *p++ != cur_e)
i++;
next_e = *p;
if (i < L.length)
return next_e;
else
return 0;
}
//在L的第i个位置之前插入新元素e
Status ListInsert(Sqlist L, int i, ElemType e)
{
ElemType* newbase, * p, * q;
if (i<1 || i>L.length + 1)
exit(ERROR);
if (L.length == L.list_size)//当前存储空间已满,再插入的话会溢出,需要增加分配
{
//realloc函数重新调整之前调用 malloc所分配的内存块的大小
newbase = (ElemType*)realloc(L.data, (L.list_size + LIST_INCREASE) * sizeof(ElemType));
if (!newbase)
{
printf("内存分配失败!\n");
exit(ERROR);
}
L.data = newbase;
L.list_size += LIST_INCREASE;
}
p = L.data + i - 1;
for (q = L.data + i - 1; q <= L.data + L.length - 1; q++)
*(q + 1) = *p;
*p = e;
L.length++;
return OK;
}
//删除L中的第i个元素
Status ListDelete(Sqlist L, int i, ElemType e)
{
ElemType* p;
if (i<1 || i>L.length)//i值不合法
return ERROR;
for ( p = L.data + i - 1; p < L.data + L.length-1; p++)
*p = *p + 1;
L.length--;
return OK;
}
//遍历顺序表,调用visit型的函数
void ListTravrse(Sqlist L, void(*visit)(ElemType &))
{
ElemType* p=L.data;
int i;
for (i = 1; i <=L.length; i++)
visit(*p++);
printf("\n");
}
4.操作菜单
代码如下(示例):
void Menu()
{
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.求指定元素的前驱\n");
printf("9.求指定元素的后继\n");
printf("10.在线性表指定位置插入元素\n");
printf("11.删除线性表指定位置的元素\n");
printf("12.显示线性表\n");
printf("13.获取线性表的元素\n");
printf("14.合并两个非递减线性表\n");
printf("输出一个负数退出\n");
printf("\n");
}
5.调用菜单
void Choice(Sqlist L)
{
while (1)
{
int choice, result;
ElemType i = 0, e = 0;
printf("请输入菜单序号:\n");
scanf("%d", &choice);
if (choice < 0)
{
printf("结束操作!");
exit(ERROR);
}
switch (choice)
{
case 1:
InitList(L);
break;
case 2:
DestoryList(L);
printf("操作成功!");
break;
case 3:
ClearList(L);
printf("操作成功!");
break;
case 4:
if (ListEmpty(L))
printf("线性表非空\n");
else
printf("线性表为空\n");
break;
case 5:
printf("线性表的长度为:%d\n", ListLength(L));
break;
case 6:
printf("请输入你想要获取的位置:");
scanf("%d", &i);
result = GetData(L, i, e);
printf("此位置的元素为:%d\n", e);
break;
case 7:
printf("请输入你想要获取的元素:");
scanf("%d", &e);
result = LocateData(L, e, Compare);
printf("此元素的位置为:%d\n", result);
break;
case 8:
i = 0;
printf("请输入你想哪个元素的前驱:");
scanf("%d", &e);
result = PriorData(L, e, i);
if (result)
printf("此元素的前驱为:%d\n", result);
break;
case 9:
i = 0;
printf("请输入你想哪个元素的后继:");
scanf("%d", &e);
result = NextData(L, e, i);
if (result)
printf("此元素的后继为:%d\n", result);
break;
case 10:
int n;
printf("请输入你要插入的位置:");
scanf("%d", &i);
printf("请输入你要插入的数据:");
scanf("%d", &e);
result = ListInsert(L, i, e);
printf("插入成功!此时的线性表为: ");
ListTravrse(L, Print);
break;
case 11:
printf("请输入你要删除的位置:");
scanf("%d", &i);
result = ListDelete(L, i, e);
printf("删除成功!此时的顺序表为: ");
ListTravrse(L, Print);
break;
case 12:
printf("此时线性表为:");
ListTravrse(L, Print);
break;
case 13:
InsertData(L);
break;
case 14:
Sqlist La, Lb, Lc;
InitList(La);
InitList(Lb);
InsertData(La);
InsertData(Lb);
MergeList(La, Lb, Lc);
printf("合并后的线性表为: ");
ListTravrse(Lc, Print);
break;
default:
printf("输入错误!!!请重新选择!\n");
break;
}
Menu();
}
}
6.主函数
代码如下(示例):
int main()
{
Sqlist L;
ElemType e;
int i;
InitList(L);
Menu();
Choice(L);
return 0;
}
总结
提示:这里对文章进行总结:
例如:通过对基本操作有机地结合,就可以对线性表进行复杂的处理。