【数据结构】顺序表最全基本操作

题干

这是一道适合初学线性表顺序存储的题目。我会对它进行逐一拆解,代码实现。

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;
}
  1. 线性表长度指的是表中元素的个数

  2. 分配的存储容量时线性表能容纳元素的最多个数,常设为像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;
}

运行结果

顺序表特点

优点

  • 逻辑相邻,物理相邻
  • 可随机存取任一元素
  • 存储空间使用紧凑

缺点

  • 插入、删除操作需要移动大量元素
  • 预先分配空间需按最大空间分配,利用不充分
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值