线性表-顺序存储结构

来源:互联网 发布:查询数据库名称 编辑:程序博客网 时间:2024/05/04 10:19
线性表-顺序存储结构


下面是用c语言实现的线性表,顺序存储结构,是用一维数组实现的,即把第一个数据元素存到数组下标为0的位置中,接着把线性表相邻的元素存储在数组相邻的位置。这种顺序存储方式优点是可以快速的存取表中任一位置的元素,但是插入和删除需要移动大量元素,当线性表变化较大时,难以确定存储空间的容量,因为这种存储方式需要提前确定数组的长度,下面的MAXSIZE就是提前指定的数组长度。
正如上面介绍,线性表顺序存储结构是利用数组实现的,那么该线性表的基本操作,无非是对数组中元素的操作,那么我们很容易想到操作有:给数组特定位置添加元素、删除特定位置元素、确定线性表当前长度、清空线性表、初始化线性表等等,可以参考下面程序学习。

注:详细内容可以参考程杰的《大话数据结构》,下面代码是这本书提供的源代码


////  main.c//  线性表-顺序存储////#include "stdio.h"#include "stdlib.h"#include "math.h"#include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 20 /*线性表最大长度 */typedef int Status;typedef int ElemType;Status visit(ElemType c){    printf("%d ",c);    return OK;}typedef struct{    ElemType data[MAXSIZE];        /*  数组,存储数据元素 */    int length;                                /* 线性表当前长度 */}SqList;                           /* 初始化线性表*/Status InitList(SqList *L){    L->length=0;    /* L是指向链表的指针,L->length是指该指针指向链表中的length元素 */    return OK;}/* 判断线性表是否为空 */Status ListEmpty(SqList L){    if(L.length==0)        return TRUE;    else        return FALSE;}/* 清空线性表 */Status ClearList(SqList *L){    L->length=0;    return OK;}/* 返回线性表当前长度 */int ListLength(SqList L){    return L.length;}/* 获取线性表第i个元素,并用e返回*/Status GetElem(SqList L,int i,ElemType *e){    if(L.length==0 || i<1 || i>L.length)        return ERROR;    *e=L.data[i-1];        return OK;}/* 判断线性表中是否存在值为e的元素,若存在,返回它的位置 */int LocateElem(SqList L,ElemType e){    int i;    if (L.length==0)        return 0;    for(i=0;i<L.length;i++)    {        if (L.data[i]==e)            break;    }        if(i>=L.length)//不存在该元素,返回0        return 0;        return i+1;}/* 将e元素插入到线性表的第i个位置 */Status ListInsert(SqList *L,int i,ElemType e){    int k;    if (L->length==MAXSIZE)  /* 链表最大长度 */        return ERROR;    if (i<1 || i>L->length+1)/* 插入位置大于表长,或者小于1,报错 */        return ERROR;        if (i<=L->length)        /* 插入位置不在表尾 */    {        for(k=L->length-1;k>=i-1;k--)  /*将第i个位置至最后元素都向后移动一位 */            L->data[k+1]=L->data[k];    }    L->data[i-1]=e;          /* 将数据e插入到第i个位置 */    L->length++;        return OK;}/* 删除线性表中第i个元素,并用e返回被删除的元素 */Status ListDelete(SqList *L,int i,ElemType *e){    int k;    if (L->length==0)        return ERROR;    if (i<1 || i>L->length)        return ERROR;    *e=L->data[i-1];    if (i<L->length)    {        for(k=i;k<L->length;k++)            L->data[k-1]=L->data[k];    }    L->length--;    return OK;}/* 打印线性表中每个元素 */Status ListTraverse(SqList L){    int i;    for(i=0;i<L.length;i++)        visit(L.data[i]);    printf("\n");    return OK;}/*  */void unionL(SqList *La,SqList Lb){    int La_len,Lb_len,i;    ElemType e;    La_len=ListLength(*La);    Lb_len=ListLength(Lb);    for (i=1;i<=Lb_len;i++)    {        GetElem(Lb,i,&e);   //获取链表Lb中第i个元素,并用e返回        if (!LocateElem(*La,e))   //判断条件,若链表La中不存在值为e的元素,执行下面操作            ListInsert(La,++La_len,e);//将e插入到链表La的表尾    }}int main(){        SqList L;    ElemType e;    Status i;    int j,k;    i=InitList(&L);    printf("初始化L后:L.length=%d\n",L.length);    for(j=1;j<=5;j++)        i=ListInsert(&L,1,j);    printf("在L的表头依次插入1~5后:L.data=");    ListTraverse(L);        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("L.length=%d \n",L.length);        ListInsert(&L,1,0);    printf("在L的表头插入0后:L.data=");    ListTraverse(L);    printf("L.length=%d \n",L.length);        GetElem(L,5,&e);    printf("第5个元素的值为:%d\n",e);    for(j=3;j<=4;j++)    {        k=LocateElem(L,j);        if(k)            printf("第%d个元素的值为%d\n",k,j);        else            printf("没有值为%d的元素\n",j);    }            k=ListLength(L);    for(j=k+1;j>=k;j--)    {        i=ListDelete(&L,j,&e);        if(i==ERROR)            printf("删除第%d个数据失败\n",j);        else            printf("删除第%d个的元素值为:%d\n",j,e);    }    printf("依次输出L的元素:");    ListTraverse(L);        j=5;    ListDelete(&L,j,&e); /* …æ≥˝µ⁄5∏ˆ ˝æ› */    printf("删除第%d个的元素值为:%d\n",j,e);        printf("依次输出L的元素:");    ListTraverse(L);            SqList Lb;    i=InitList(&Lb);    for(j=6;j<=15;j++)        i=ListInsert(&Lb,1,j);        unionL(&L,Lb);        printf("依次输出合并了Lb的L的元素:");    ListTraverse(L);         return 0;}

运行结果如下:
初始化L后:L.length=0在L的表头依次插入1~5后:L.data=5 4 3 2 1 L.length=5 L 是否为空:i=0(1:是 0:否)清空L后:L.length=0L 是否:i=1(1:是 0:否)在L的表尾依次插入1~10后:L.data=1 2 3 4 5 6 7 8 9 10 L.length=10 在L的表头插入0后:L.data=0 1 2 3 4 5 6 7 8 9 10 L.length=11 第5个元素的值为:4第4个元素的值为3第5个元素的值为4删除第12个数据失败删除第11个的元素值为:10依次输出L的元素:0 1 2 3 4 5 6 7 8 9 删除第5个的元素值为:4依次输出L的元素:0 1 2 3 5 6 7 8 9 依次输出合并了Lb的L的元素:0 1 2 3 5 6 7 8 9 15 14 13 12 11 10 Program ended with exit code: 0


ps:读这段代码时候,开始有一点不很清楚地方是L->length和L->data这种表达,后来才明白,这中表述中,L是一个指针变量,指向SqList的指针,而L->length的意思就是该指针L指向的SqList结构中的length。
可以通过下面小程序更清晰了解:
#include <iostream>struct pero{    char name[20];    int age;    int tall;};int main(int argc, const char * argv[]) {        pero wang={        "weiwei",        26,        180    };    pero* pst=&wang;    std::cout<<wang.age<<std::endl;    pst->age=20;    std::cout<<wang.age<<std::endl;    return 0;}

运行结果:26和20
可见,通过pst->age对pst指针指向的wang中的age元素进行了赋值操作。




0 0