线性表

线性表的顺序表示指的是一组地址连续的存储单元依次存储线性表的数据元素。

假设线性表的每个元素需占用L个存储单元,并以所占的第一个单元的存储地址作为数据元素的存储位置。则线性表中的第i +1个数据元素的存储位置LOCai+1)和第i个数据元素的存储位置LOC(ai)之间满足如下关系:

LOC(ai+1) = LOC(ai) + L

一般来说,线性表的第i个数据元素ai的存储位置为

LOC(ai) = LOC(a1) + (i - 1)*L

 

由于高级程序设计语言中的数组类型也有随机存取的特性,因此,通常都用数组来描述数据结构中的顺序存储结构。由于线性表的长度可变,且所需最大存储空间随问题而不同,则在C语言中可用动态分配一维数组。

       下面是线性表的动态分配顺序存储结构

#define LIST_INIT_SIZE 100

//线性表存储空间的初始分配量以sizeof(ElemType)为单位

#define LISTINCREMENT 10

//线性表存储空间的分配增量,当空间不够时给它的增量

typedef int ElemType;//元素类型

typedef int Status;//返回1为成功,0失败

typedef struct

{

    ElemType * List;//线性表的第一个元素

    int Length;//元素个数

    int ListSize;//线性表的占用内存空间大小

}SqList;

 

       下面是初始化顺序表的函数

/*初始化线性表 成功返回1,错误返回0*/

Status InitList(SqList * L)

{

    L->List = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));

    //构造一个空的线性表

    if(!L->List){return 0;}//分配空间失败

    L->Length = 0;//0个元素

    L->ListSize = LIST_INIT_SIZE;//这个是以sizeof(ElemType为单位)

    return 1;//初始化完毕

}

 

一般情况下,在第i1 <=  i  <= n)个元素之前插入一个元素时,需将第n至第i(共n - i + 1)个元素向后移动一个位置,下面是插入元素的算法:

/*插入数据*/

Status ListInsert(SeqList * L, int i, ElemType e)

{

    ElemType *p,*q;

    if(i > L->Length + 1 || i < 1){return 0;}//插入位置错误

    //Length+1是可能插入的最大位置,记得要加1哦

    if(L->Length >= L->ListSize)//空间不够

    {

       ElemType * NewBase;//新地址

        NewBase = (ElemType *)realloc(L->List,

           (L->ListSize + LISTINCREMENT) * sizeof(ElemType));

       //重新分配内存空间

       if(!NewBase)

           exit(0);//分配失败退出

       L->List = NewBase;

       L->ListSize += LISTINCREMENT;//顺序表占内存空间增加

    }

   

    p = &L->List[i-1];//要插入的位置

    q = &(L->List[L->Length-1]);//最后一个元素的位置

    for(;q >= p; --q)

       *(q+1) = *q;//依次将元素往后移动一个位置

    *p = e;//插入元素

    L->Length++;

    return 1;

}

 

       一般情况下,删除第i1<=  i  <= n)个元素需将从第i+1n共(n-i)个元素依次向前移动一个位置,删除元素的算法如下:

以下算法自己的写

/*删除数据*/

Status ListDelete(SeqList * L,int pos,ElemType * e)

{

    ElemType * temp;

    if(pos < 1 || pos > L->Length)

       return 0;//没有这个位子

    *e = L->List[pos-1];

    temp = L->List+pos-1;//这是要删除元素的位置

    while(temp != L->List+L->Length-1)

    {

       *temp = *(temp + 1);

       temp++;

    }

    L->Length--;

    return 1;

}

 

下面是查找元素是否在顺序表中

 

/*查找顺序表中是否有指定的元素*/

 

int LocateElem(SeqList * L, ElemType e,

    Status (* Compare)(ElemType e1,ElemType))

{//这里使用函数指针,相等返回0,不等返回1

    int i = 1; //表示顺序表的第一个元素位置

    ElemType * p = L->List;

    while(i <= L->Length && (*Compare)(*p++,e))

       i++;

    if(i <= L->Length)

       return i;

    return 0;

}

/*两个变量比较 相等返回0,不等返回1*/

Status ElemCompare(ElemType e1,ElemType e2)

{

    if(e1 == e2)

       return 0;//返回零上面的while就能退出循环

    return 1;

}

 

所有C语言的变量要在第一行声明,否则编译错误。提示未声明标识符。

已知线性表LA和LB中的数据元素按递增顺序排列,现在要求将LA和LB归并为一个新的线性表LC,且LC中的数据元素仍按递增顺序排列。假如,设

                     LA = (3,5,8,11)

                     LB = (2,6,8,9,11,15,20)

则                 LC = (2,3,5,6,8,9,11,11,15,20)

       从上述问题的要求可知,LC中的数据元素或是LA中的数据元素或是LB中的数据元素,则只要先设LC为空表,然后将LALB中的元素逐个插入到LC中即可。为使LC中元素按递增顺序排列,可设两个指针ij分别指向LALB中的某个元素,若设i当前所指的元素为aj当前所指的元素为b,则当前应插入到LC中的元素c

                                  a   a <= b

              c =

                                   b  a>b

显然指针ij的初值均为1,在所指元素插入LC之后,LALB中顺序后移。

上述归并算法如下:

void MergeList (List La, List Lb, List &Lc){

       InitList(Lc);//初始化Lc表,Lc表为空

       i = j = 1; k = 0;//i,j分别指向La,Lb的第一个元素,k 表是Lc的第一个元素

       La.len = ListLength(La); Lb.len = ListLength(Lb);

       while( i <= la.Len && j <= lb.len){//La和Lb都存在

       GetElement(La,i,ai);//ai是La的一个元素

       GetElement(Lb,j,bj);//bj是Lb的一个元素

       if(ai <= bj) {

ListInsert(lc,++k,ai);

       i++;

}

else{

       InsertList(lc,++l,bj);

       j++;

}

while(i <= La.len){//Lb表为空,或还有元素没插入完

       GetElement(La,i++,ai);

       ListInsert(Lc,++k,ai);

}

while(j <= Lb.len){//La表为空, 或还有元素没插入完

       GetElement(Lb,j++,bj);

       ListInsert(Lc,++k,bj);

}

}

}

转载于:https://www.cnblogs.com/zhpsdbx/archive/2012/11/17/2775163.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值