[数据结构]线性表/顺序表——用c语言实现

废话不多说,直奔主题。
在c语言中,一般使用数组来表示线性表的顺序存储结构,这样就能使其表的物理存储结构也是连续的(顺序存储结构),线性表的顺序存储结构又叫顺序表。即顺序表逻辑上相邻,物理上也相邻。为了能使数组进行顺序表的基础操作,我们还需要引入一个变量来指向顺序表的表尾。这个时候,我们可以使用结构体来将数组和变量包括进去。

首先我们先创建一个头文件,相当于一个能创建并操作顺序表的“库”。博主把此头文件命名为SeqList.h。之后再在头文件里自己定义数据类型——顺序表。

#ifndef __SEQLIST_H__
#define __SEQLIST_H__
#define MAXSIZE 20  //用来表示顺序表的最大长度
typedef char Elemtype;
 /*顺序表只能存储一种数据类型。
为方便以后替换存储类型我们把存储类型命名为Elemtype,当需要存储浮点数类型或字符类型的数据类型时只需要修改int即可*/
typedef struct{   // 定义顺序表
	elemtype elem[MAXSIZE];
	/*这里建立数组来表示顺序表,最大长度固定*/
	int last;  /* last作为指向顺序表最后一个元素的下标
	若顺序表为空,则last=-1*/
}SeqList; 
/*至此我们定义完了顺序表的数据类型。
我们以后可以用int i定义整数i一样用SeqList L定义顺序表L。*/
#endif

到此,顺序表就被定义完了。

现在我们来深度理解一下顺序表的下标表示。

{a1,a2,…,ai-1,ai,ai+1,…,an}

如上,相邻数据元素之间关系是线性的,ai-1是ai的直接前驱,ai+1是ai的直接后继。a1是顺序表的起点,它的下标是1。而c语言中数组的第一位是从0开始的!所以一定要注意数组与顺序表下标的对应。

顺序表被定义完了,但是我们还没有建立这样的顺序表。所以我们还要写一个函数用来建立一个存放数据的顺序表。

SeqList NewList(SeqList L) 
/*该函数是从顺序表首个元素赋值
所以只用来建新顺序表
想往顺序表内修改元素请看下文*/
{
    Elemtype e;  //
    for(L.last=-1;(L.last<MAXSIZE);){
        printf("please elem:");
        scanf("%c",&e);getchar();  //getchar()用来吃掉回车
        if (e=='$') break;  //输入$来结束顺序表的创建
        L.last++;
        L.elem[L.last]=e;
    }
    return L;
}

下面我们定义一个函数Locate来实现顺序表的查找操作:

int Locate(SeqList L,ElemType e) // 函数功能:在顺序表中寻找元素e,返回e第一次出现的下标。
{/*逻辑简述:从顺序表L中依次查找与e相等的元素,
若L(i)=e,找到并返回i+1,否则返回-1*/
	int i=0; //从第一个元素开始查找
	while((i<=L.last)&&(L.elem[i]!=e)) i++;
	if(i<=L.last) rerurn i+1;
	else return(-1); //没有找到就返回空序号-1
}

接下来我们开始进行顺序表的修改操作的函数的编写。

定义一个函数InsList实现顺序表的插入操作:
注意,函数定义的形式参数L是指针类型!

int InsList(SeqlList *L,int i,elemtype e) 
// 在顺序表L的第i个元素前插入e,插入成功返回1,否则返回0
{
	int k;
	if(i<1||i>L.last+2){ //判断i值是否合理
		printf("插入位置i不合法");
		return 0;
	}
	if(L->last+1>=MAXSIZES){//判断存储空间是否满了
		printf("顺序表已满,不可再插入");
		return 0;
	}
	for(k=L->last;k>=i-1;k--){ //从最后一个元素开始逐一往后挪,为e的插入在i处留出位置
		L.elem[k+1]=L.elem[k];
	}
	L->elem[i-1]=e;  // 插入e
    L->last++;  // 表长+1
    return 1; 
}

定义一个函数ListDelete实现顺序表的插入操作:
注意,函数定义的形式参数L是指针类型!

//删除操作,删除L的第i个元素并将值赋给指针e
int ListDelete(SeqList *L,int i ,Elemtype *e)
{
    int k;
    if(i<1||i>L->last+2){
        printf("删除位置%d不合法",i);
        return 0;
    }
    *e=L->elem[i-1];
    for(k=i;k<=L->elem[k];k++){
        L->elem[k-1]=L->elem[k]; //被删除元素之后的元素左移
    }
    L->last--;  // 表长-1
    return 1;
}

至此,顺序表的一些基本操作函数就写完了。我们将这些函数的定义全部放到头文件SeqList.h里。然后我们再创建一个c文件来用一下上述函数试试效果吧!

演示代码如下:

#include <stdio.h>
#include "SeqList.h"  //使用引号是因为我把此头文件和c文件放在了同一目录
int main
{
	SeqList L;char e; int a;
    SeqList *l;Elemtype *p;
    L=NewList(L);l=&L;  //建立顺序表L,指针l指向L
    printf("L.last=%d\n",L.last);  //输出一下L.last看看是否出错,其值应该是你输入的元素数量-1
    printf("输入一个你想查找的元素:");
    scanf("%c",&e);getchar();
    printf("该元素在第 %d位.\n",Locate(L,e));

    printf("插入k成功了吗(成功1不成功0)?:%d",InsList(l,2,'k'));
    printf("k在第 %d位.\n",Locate(L,'k'));

	a=ListDelete(l,3,p);  //删除第三个元素
    printf("删除操作成功了吗?:%d,把 %c删除了",a,*p);
	return 0;
}

然后执行代码:(红字为博主输入)
效果如下:


please elem:a
please elem:b
please elem:c
please elem:d
please elem:$
L.last=3
输入一个你想查找的元素:b
该元素在第 2位.
插入k成功了吗(成功1不成功0)?:1
k在第 2位
删除操作成功了吗?:1,把 b删除了


所以,我们便可以在以后使用如上介绍的函数来实现顺序表的操作了。

顺序表的缺点

从函数中可以看到。当在长度为n的顺序表上删除第i位元素,需要把n-i个元素向左移动,效率是很慢的。插入操作同理。
而且为顺序表的存储分配空间是从一开始就宏定义好的(#define MAXSIZE 20 ),不能动态分配,十分不灵活,而且表长很长时难以确定分配多少存储空间。
在这个时候,链式存储就派上了用场。


人生如逆旅,我亦是行人

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值