题干
这是一道适合初学线性表顺序存储的题目。我会对它进行逐一拆解,代码实现。
1.生成随机个数,首先随机初始化顺序表
2.输出顺序表
3.从键盘输入要查找的元素e,调用函数,查找顺序表L中值为e的元素的位序
4.输入要插入的元素f和插入的位置,调用插入函数,若插入成功,输出更新后的列表。
5.输入要删除的元素的位置,调用删除函数
6.编程实现两个线性表的合并
蓝字部分要求函数实现
预备知识
typedef
关键字typedef用于自定义变量类型名,常见于结构体定义,状态函数定义,结构体成员定义。
typedef int ElemType;//定义ElemType为int,在结构体中使用
typedef int Status;//Status函数只返回函数状态值,一般为0或1,可用布尔类型的函数代替
typedef Struct List{
ElemType* data;
ElemType length;
ElemType MaxSize;
}SqList;//此后调用该结构体时,变量类型名写SqList即可
ElemType
ElemType是一个抽象的数据类型,用于表示数据结构中的元素类型。它可以根据具体应用的需要来定义,可以是任何合法的数据类型,比如整数、字符、浮点数、字符串等。
在不同的数据结构中,ElemType的具体定义可能会有所不同。例如,在线性表中,ElemType可以表示表中的每个元素。
直接更改定义时ElemType的类型,即可在代码中用到ElemType的地方全部修改,其方便性类似于define,详见下文。
define
关键字define用于在程序中创建一个标识符,并分配相应的内存空间。
#define N 10
之后代码中N等同于数字10,若需改动该数字,只需在宏定义里改N的值,不必在代码里逐个修改。
如何每次生成不同的随机数?
#include <stdlib.h>
#include <time.h>
这是两个必须添加的头文件。<stdlib.h>中的rand函数用于生成随机数,<time.h>中的srand函数用于添加时间戳,确保每次运行代码时生成的数不同。
srand(unsigned int)time(NULL);//设置时间随机种子
for(int i=0;i<N;i++)
{
a[i]=rand();
b[i]=rand()%100+1;
}
数组a的元素为比较大的随机整数,数组b的元素为大于等于1且小于等于100的随机整数。这只是一种比较基础的随机数生成方法。
定义函数
准备工作
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MaxSize 100
#define OK 1
#define ERROR 0
#define OVERLOW -2
typedef int Status;
typedef int ElemType;
建立空顺序表
typedef struct{
ElemType *elem;//基地址
int length;//线性表当前长度
int listsize;//当前为线性表分配的存储容量(以sizeof(ElemType)为单位)
}SqList;
Status InitList(SqList &L)
{
L.elem=(ElemType*)malloc(MaxSize*sizeof(ElemType));
if(!L.elem) exit(OVERLOW);
L.length=0;
L.listsize=MaxSize;
return OK;
}
-
线性表长度指的是表中元素的个数
-
分配的存储容量时线性表能容纳元素的最多个数,常设为像100这样比较大的数,线性表长度不能超过分配的存储容量。
随机初始化顺序表
Status ListWrite(SqList &L)
{
printf("向线性表中输入的元素个数\n");
scanf("%d",&L.length);
if((!L.elem)||(L.length>MaxSize))
return ERROR;
srand((unsigned int)time(NULL));
for(int i=0;i<L.length;i++)
L.elem[i]=rand()%100+1;
return OK;
}
输出顺序表
void PrintList(SqList L)
{
for(int i=0;i<L.length;i++)
printf("%5d",L.elem[i]);
}
按值查找
int LocateElem(SqList L,ElemType e)
{
for(int i=1;i<L.length;i++)
if(L.elem[i-1]==e)
return i;
return 0;
}
插入操作
Status ListInsert(SqList &L,int i,ElemType e)
{
if((i<1)||(i>L.length+1))
return ERROR;
if(L.length>L.listsize)
return ERROR;
for(int j=L.length;j>=i;j--)
L.length[j]=L.elem[j-1];
L.length ++;
L.elem[i-1]=e;
return OK;
}
删除操作
int ListDelet(SqList &L,int i)
{
int e;
if((i<1)||(i>L.length+1))
return ERROR;
e=L.elem[i-1];
for(int j=i;j<L.length;j++)
L.elem[j-1]=L.elem[j];
L.length--;
return e;
}
线性表合并
void MergeList(SqList a,SqList b,SqList &c)
{
ElemType *pa,*pb,*pc,*palast,*pblast;
pa=a.elem;pb=b.elem;
c.listsize=c.length=a.length+b.length;
pc=c.elem=(ElemType*)malloc(sizeof(ElemType)*c.listsize);
if(!c.elem) exit(OVERLOW)
palast=pa+a.length-1;
pblast=pb+b.length-1;
while((pa<=palast)&&(pb<=pblast))
{
if(*pa<=*pb)
*pc++=*pa++;
if(*pb<=*pa)
*pc++=*pb++;
}
while(pa<=palast)
*pc++=*pa++;
while(pb<=pblast)
*pc++=*pb++;
}
完整实现
源代码
编译器:Visual Studio 2022
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
constexpr auto MaxSize = 100;
constexpr auto OK = 1;
constexpr auto ERROR = 0;
constexpr auto OVERLOW = -2;
typedef int Status;
typedef int ElemType;
typedef struct {
ElemType* elem;//基地址
int length;//线性表当前长度
int listsize;//当前为线性表分配的存储容量(以sizeof(ElemType)为单位)
}SqList;
Status InitList(SqList& L)
{
L.elem = (ElemType*)malloc(MaxSize * sizeof(ElemType));
if (!L.elem) exit(OVERLOW);
L.length = 0;
L.listsize = MaxSize;
return OK;
}
Status ListWrite(SqList &L)
{
printf("向线性表中输入的元素个数\n");
scanf_s("%d", &L.length);
if ((!L.elem) || (L.length > MaxSize))
return ERROR;
srand((unsigned int)time(NULL));
for (int i = 0; i < L.length; i++)
L.elem[i] = rand() % 100 + 1;
return OK;
}
//*************************************************
Status CopyList(SqList& a,SqList &b)
{
if(a.length!=b.length) exit(OVERLOW);
for(int i=0;i<b.length;i++)
b.elem[i]=a.elem[i];
}//*************************************************
void PrintList(SqList L)
{
for (int i = 0; i < L.length; i++)
printf("%d\n", L.elem[i]);
printf("\n");
}
int LocateElem(SqList L, ElemType e)
{
for (int i = 1; i < L.length; i++)
if (L.elem[i - 1] == e)
return i;
return 0;
}
Status ListInsert(SqList &L, int i, ElemType e)
{
if ((i < 1) || (i > L.length + 1))
return ERROR;
if (L.length > L.listsize)
return ERROR;
for (int j = L.length; j >= i; j--)
L.elem[j] = L.elem[j - 1];
L.length++;
L.elem[i - 1] = e;
return OK;
}
int ListDelet(SqList& L, int i)
{
int e;
if ((i < 1) || (i > L.length + 1))
return ERROR;
e = L.elem[i - 1];
for (int j = i; j < L.length; j++)
L.elem[j - 1] = L.elem[j];
L.length--;
return e;
}
void MergeList(SqList a, SqList b, SqList& c)
{
ElemType* pa, * pb, * pc, * palast, * pblast;
pa = a.elem; pb = b.elem;
c.listsize = c.length = a.length + b.length;
pc = c.elem = (ElemType*)malloc(sizeof(ElemType) * c.listsize);
if (!c.elem) exit(OVERLOW);
palast = pa + a.length - 1;
pblast = pb + b.length - 1;
while ((pa <= palast) && (pb <= pblast))
{
if (*pa <= *pb)
*pc++ = *pa++;
if (*pb <= *pa)
*pc++ = *pb++;
}
while (pa <= palast)
*pc++ = *pa++;
while (pb <= pblast)
*pc++ = *pb++;
}
int main (void)
{
SqList a{}, b{}, c{}; int m=0, i=0, e = 0;
InitList(a);
ListWrite(a);
printf("输出a表\n");
PrintList(a);
InitList(b);
ListWrite(b);
printf("输出b表\n");
PrintList(b);
InitList(c);
MergeList(a, b, c);
printf("输出ab合并成的表\n");
PrintList(c);
printf("下列操作在a表中进行\n");
printf("输入要查找的元素:\n");
scanf_s("%d",&m);
LocateElem(a, m);
printf("找到了该元素,在第%d位:\n", LocateElem(a, m));
//*********************************************
SqList d{};
InitList(d);
printf("复制a表\n");
ListWrite(d);
CopyList(a, d);
printf("确认保留了a表\n");
PrintList(d);
//*********************************************
printf("输入要插入的元素\n");
scanf_s("%d",&e);
printf("插入在原表第几位前\n");
scanf_s("%d", &i);
ListInsert(a, i, e);
printf("输出新表\n");
PrintList(a);
printf("要删除原表第几位\n");
scanf_s("%d",&i);
printf("输出要删除元素的值\n");
printf("%d\n", ListDelet(d, i));
printf("输出新表\n");
PrintList(d);
return 0;
}
运行结果
顺序表特点
优点
- 逻辑相邻,物理相邻
- 可随机存取任一元素
- 存储空间使用紧凑
缺点
- 插入、删除操作需要移动大量元素
- 预先分配空间需按最大空间分配,利用不充分