线性表的顺序表示指的是一组地址连续的存储单元依次存储线性表的数据元素。
假设线性表的每个元素需占用L个存储单元,并以所占的第一个单元的存储地址作为数据元素的存储位置。则线性表中的第i +1个数据元素的存储位置LOC(ai+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;//初始化完毕
}
一般情况下,在第i(1 <= 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;
}
一般情况下,删除第i(1<= i <= n)个元素需将从第i+1至n共(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为空表,然后将LA或LB中的元素逐个插入到LC中即可。为使LC中元素按递增顺序排列,可设两个指针i和j分别指向LA和LB中的某个元素,若设i当前所指的元素为a,j当前所指的元素为b,则当前应插入到LC中的元素c为
a 当 a <= b时
c =
b 当 a>b时
显然指针i和j的初值均为1,在所指元素插入LC之后,LA或LB中顺序后移。
上述归并算法如下:
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);
}
}
}