首页 > 技术文章 > 线性表的顺序存储(C代码实现)

liuzeyu12a 2019-01-19 23:46 原文

线性表的顺序存储--

线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

线性表示什么?借助网上大佬的一个例子

 

小学生放学都是要按顺序排队的,一个接一个,每个小学生的前后位置是固定的,这样便于迅速清点。

 

其实这就是一个线性表,从这件事里我们就可以找到很多关于线性表的特性,如

 

1、线性表是一个序列,它是有顺序的(排队)

 

2、第一个元素无前驱,最后一个无后继,其他每个元素都有一个前驱和后继(一个接一个)

 

3、元素是有限的(小学生的个数是有限的)

 

4、数据类型都相同(都是小学生在排队)

那么我们如何定义一个节点呢?

 /*定义线性表类型*/
  typedef struct{
    ElemType data[MAXSIZE];
     int length;
}sqList;

  

结构较简单,一个数组用于存放元素信息 和一个长度用于下面操作

 

代码实现的功能包括线性表的初始化,判断是否为空、清空、增加元素、删除元素、合并线性表等操作。

 

#include <stdio.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20   /*初始化存储空间*/

/*取别名,便以操作*/
typedef int Status;
typedef int ElemType;

/*定义线性表类型*/
typedef struct{
    ElemType data[MAXSIZE];
    int length;
}sqList;

/*初始化顺序线性表*/
Status InitList(sqList *L){
    L->length=0;
    return OK;
}

/*初始条件:顺序表已存在,操作结果:若L为空,则返回TRUE,否则返回FALSE*/
Status ListEmpty(sqList* L){
    if(L->length==0)
        return TRUE;
    else
    return FALSE;
}

/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Status ClearList(sqList* L){
    L->length=0;
    return OK;
}

/*初始条件:顺序线性表L已存在。操作结果:获取线性表的长度*/
Status ListLength(sqList* L){
    return L->length;
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
Status GetElem(sqList* L,int i, ElemType* e){
    if(i<1 || i>L->length)
        return ERROR;
    else
        *e = L->data[i-1];
        return OK;
} 

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
Status LocalElem(sqList* L,ElemType e){
    int i;
    if(L->length==0)
        return ERROR;
    for(i=0;i<L->length;i++)
            if(e==L->data[i])
                break;

    if(i>=L->length)   //没有找到相匹配的元素
        return 0;
        return i+1;
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert(sqList* L,int i,ElemType e){

    int k;
    if(L->length == MAXSIZE) return ERROR;
    if(i<1 || i>L->length+1) return ERROR;
    for(k=L->length-1;k>=i-1;k--)
        L->data[k+1]=L->data[k];
    L->length++;
    L->data[i-1]=e ;
    return OK;
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(sqList* L,int i,ElemType* e){

    int k;
    if(i<1 || i>L->length) return ERROR;
    else
        *e = L->data[i-1];
    for(k=L->length-1;k>i;k--)
        L->data[k]=L->data[k+1];
    L->length--;
    return OK;
}

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status ListTraverse(sqList* L){
    int i;
    for(i=0;i<L->length;i++)
        printf("%d ",L->data[i]);
    return OK;
}

/*求并集*/
void unioList(sqList* La,sqList* Lb){

    int La_len,Lb_len,i;
    ElemType e;
    La_len = La->length;
    Lb_len = Lb->length;

    for(i=1;i<=Lb_len;i++){
    /*用e来获取Lb线性表中的值*/
    GetElem(Lb,i,&e);
    if(!LocalElem(La,e))
        ListInsert(La,++La_len,e);
    }
}

int main(){

    //构造一个有10个数的Lb
    sqList Lb;
    sqList L;
    ElemType e;
    int i,j,k;

    InitList(&L); //初始化
    printf("初始化L后:L.length=%d\n",L.length);

        /*插入数据*/
    for(j=1;j<=5;j++)
        ListInsert(&L,1,j);
    printf("在L的表头依次插入1~5后:L.data=");
    ListTraverse(&L);  //遍历输出
    printf("\n");

    printf("L.length=%d \n",L.length);
    i = ListEmpty(&L); //判断是否为空
    printf("L 是否为空:i=%d(1:是 0:否)\n",i); 

    i =ClearList(&L); //清空线性表
    printf("清空L后:L.length=%d\n",L.length);
    i = ListEmpty(&L);//判断是否为空
    printf("L 是否为空:i=%d(1:是 0:否)\n",i); 

    for(j=1;j<=10;j++)  /*插入数据*/
        ListInsert(&L,j,j);
    printf("在L的表尾依次插入1~10后:L.data=");
    ListTraverse(&L);
    printf("\n");
    printf("L.length=%d\n",L.length);


    GetElem(&L,5,&e); //取得5号元素
    printf("L中第五个元素=%d\n",e);

    for(j=7;j<9;j++){
    k=LocalElem(&L,j);    //判断是否存在元素
    if(k)
        printf("存在%d号元素=%d\n ",j,k);
    else
        printf("No存在%d号元素\n");
    }

    k=ListLength(&L);
    for(j=k+1;j>=k;j--){    
        i=ListDelete(&L,j,&e); //删除第j个元素
    if(i == ERROR)
        printf("删除第%d个数据失败\n",j);
    else
        printf("删除第%d个的元素值为:%d\n",j,e);
    }    
    printf("依次输出L的元素:");
    ListTraverse(&L);

    j=8; 
    ListDelete(&L,j,&e);  //删除8号元素
    printf("删除第%d个的元素值为:%d\n",j,e);
    printf("依次输出L的元素:");
    ListTraverse(&L);
    printf("\n");

    /*合并La ,Lb*/
    InitList(&Lb);
    /*插入数据*/
    for(j=10;j<=100;j+=10){
        ListInsert(&Lb,1,j);
    }
    unioList(&L,&Lb);   //合并
    printf("依次输出合并了Lb的L的元素:");
    ListTraverse(&L);

    return 0;
}

 

  

 

 

注意点:

1、线性表其实可以理解是数组的一种特殊表示,但线性表的数据是从1开始的,数组的元素是从0开始的。

2、线性表的顺序存储结构,在存、读哪个数据的时候,不管在哪个位置,时间复杂度都是O(1),而在插入和删除时,时间复杂度时O(n)。

3、线性表的优点:无需为表示表中元素之间的逻辑关系而增加额外的存储空间;可以快速的存取表中的任意一个位置的元素。

4、线性表的缺点:插入和删除数据时需要移动大量的数据;当线性表长度变化较大时,难以确定存储空间的容量;容易造成存储空间的 ”碎片“

Java代码实现见下一篇。

推荐阅读