您的位置:首页 > 其它

线性表的静态单链表存储结构

2016-05-20 20:04 309 查看
/*
借用一维数组来描述线性链表
—————— 线性表的静态单链表存储结构——————
#define MAXSIZE 1000 //链表的最大长度
typedef struct
{
ElemType data;
int cur;
}component,SLinkList[MAXSIZE];
这种描述方法便于不设“指针”类型的高级程序设计语言中使用链表结构
如上描述的链表中,数组的一个分量表示一个结点,同时用游标(指示器cur)代替指针指示结点在数组中的相对位置
数组的第零分量可看成头结点,其指针域指示链表的第一个结点
这种存储结构仍需要预先分配一个较大的空间,但在线性链表的插入和删除操作时不需要移动元素,
仅需修改指针(cur),仍具有链式存储结构的优点,把这种用数组描述的链表起名叫 静态链表
*/

#include <stdio.h>

#define MAXSIZE 100 //链表的最大长度
typedef struct
{
int data;
int cur;
}component,SLinkList[MAXSIZE];

void InitList(SLinkList L); //构造一个空的链表

//以下两个函数被函数ListInsert()调用
int Malloc(SLinkList space);
int ListLength(SLinkList L); //返回L中数据元素的个数
bool ListInsert(SLinkList L,int i,int e); //在L中第i个元素之前插入新的数据元素e

bool ListTraverse(SLinkList L); //输出线性表的数据
void ListEmpty(SLinkList L); //判断线性表是否为空
bool ClearList(SLinkList L); //将L置为空表
bool GetElem(SLinkList L,int i,int *e); //用e返回L中第i元素的值
int LocateElem(SLinkList L,int e);
bool PriorElem(SLinkList L,int cur_e,int *pre_e);
bool NextElem(SLinkList L,int cur_e,int *next_e);
void Free(SLinkList space,int k);
bool ListDelete(SLinkList L,int i,int *e);

int main()
{
int j, k;
int e, e0;
SLinkList L;
InitList(L);
for(j = 1; j <= 5; j++)
ListInsert(L,1,j);
printf("在L的表头依次插入1-5后:L = ");
ListTraverse(L);

ListEmpty(L); //判断L是否为空
printf("len = %d\n",ListLength(L));

ClearList(L); //清空链表
ListEmpty(L); //判断L是否为空

for(j = 1; j <= 10; j++)
ListInsert(L,j,j);
printf("在L的表中依次插入1-10后:L = ");
ListTraverse(L);

GetElem(L,5,&e);//把第5个元素赋给 e
printf("第5个元素的值为:%d\n",e);

for(j = 1; j <= 10; j++)
{
k = LocateElem(L,j);
if(k)
printf("值为%d的元素在静态链表中的位序为%d\n",j,k);
else
printf("没有值为%d的元素\n",j);
}

for(j = 1; j <= 2; j++) //测试头两个数据
{
GetElem(L,j,&e0); //把第j个数据赋给e0
PriorElem(L,e0,&e); //求e0的前驱
if( PriorElem(L,e0,&e) )
printf("元素%d的前驱为:%d\n",e0,e);
else
printf("元素%d无前驱\n",e0);
}

for(j = ListLength(L) - 1; j <= ListLength(L); j++) //最后两个数据
{
GetElem(L,j,&e0); //把第j个元素赋给e0;
NextElem(L,e0,&e); //求e0的后继
if( NextElem(L,e0,&e) )
printf("元素%d的后继为:%d\n",e0,e);
else
printf("元素%d无后继\n",e0);
}

k = ListLength(L); //k为表长
ListDelete(L,k,&e);
printf("删除的元素为: %d\n",e);
ListDelete(L,k-1,&e);
printf("删除的元素为: %d\n",e);
printf("依次输出L的元素:");
ListTraverse(L); //输出元素的值

return 0;
}

void InitList(SLinkList L) //构造一个空的链表
{	//表头为L的最后一个单元L[MAXSIZE-1] ,其余单元链成一个
//备用链表,表头为L的第一个单元L[0].cur, "0"表示空指针
int i;
L[MAXSIZE-1].cur = 0; //L的最后一个单元为空链表的表头
for(i = 0; i < MAXSIZE - 2; i++) //将其余单元链接成以L[0]为表头的备用链表
L[i].cur = i + 1;
L[MAXSIZE-2].cur = 0;
}

bool ListInsert(SLinkList L,int i,int e) //在L中第i个元素之前插入新的数据元素e
{
int l, j, k = MAXSIZE - 1; //k指向表头
if(i < 1 || i > ListLength(L) + 1)
return false;
j = Malloc(L); //申请新单元
if(j) //申请成功
{
L[j].data = e; //赋值给新单元
for(l = 1; l < i; l++) //移动第i-1个元素
k = L[k].cur;
L[j].cur = L[k].cur;
L[k].cur = j;
return true;
}
return false;
}

int ListLength(SLinkList L) //返回L中数据元素的个数
{
int j = 0, i = L[MAXSIZE-1].cur; //i指向第一个元素
while(i) //没到静态链表尾
{
i = L[i].cur; //指向下一个元素
j++;
}
return j;
}

int Malloc(SLinkList space)
{	//若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回 0
int i = space[0].cur;
if(i) //备用链表非空
space[0].cur = space[i].cur; //备用链表的头节点指向原备用链表的第二个结点
return i; //返回
}

bool ListTraverse(SLinkList L) //输出线性表的数据
{
int i = L[MAXSIZE-1].cur; //指向第一个元素
while(i) //没有到静态链表尾
{
printf("%d ",L[i].data);
i = L[i].cur; //指向下一个元素
}
printf("\n");
return true;
}

void ListEmpty(SLinkList L) //判断线性表是否为空
{
if(L[MAXSIZE-1].cur == 0) //表为空
printf("链表为空\n");
else
printf("链表不为空\n");
}

bool ClearList(SLinkList L) //将L置为空表
{
int i, j, k;
i = L[MAXSIZE-1].cur; //链表第一个结点的位置
L[MAXSIZE-1].cur = 0; //链表空
k = L[0].cur; //备用链表第一个结点的位置
L[0].cur = i; // 把链表的结点连接到备用链表的表头
while(i) //没有到表尾
{
j = i;
i = L[i].cur; //指向下一个元素
}
L[j].cur = k; //备用链表的第一个结点连接到链表的尾部
return true;
}

bool GetElem(SLinkList L,int i,int *e) //用e返回L中第i元素的值
{
int l,k = MAXSIZE - 1; //K指向表头序号
if(i < 1|| i > ListLength(L))
return false;
for(l = 1; l <= i; l++) //移动到第i个元素处
k = L[k].cur;
*e = L[k].data;
return true;
}

int LocateElem(SLinkList L,int e)
{
//在静态单链线性表L中查找第i个值为e的元素 若找到,则返回它在L中的位序
int i = L[MAXSIZE-1].cur; //i指示表中第一个结点
while(i && L[i].data != e) //在表中顺序查找
i = L[i].cur;
return i;
}

bool PriorElem(SLinkList L,int cur_e,int *pre_e)
{
// 若cur_e是L的数据元素,且不是第一个 则用pre_e返回它的前驱
int j, i = L[MAXSIZE-1].cur; //i指示链表第一个结点的位置
do
{
//向后移动结点
j = i;
i = L[i].cur;
}while(i && cur_e != L[i].data);
if(i) //找到该元素
{
*pre_e = L[j].data;
return true;
}
return false;
}

bool NextElem(SLinkList L,int cur_e,int *next_e)
{
//若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继
int j, i = LocateElem(L,cur_e); //在L中查找第一个值为cur_e元素的位置
if(i) //L中存在cur_e
{
j = L[i].cur; //cur_e的后继位置
if(j) //cur_e有后继
{
*next_e = L[j].data;
return true; //cur_e元素有后继
}
}
return false;
}

bool ListDelete(SLinkList L,int i,int *e)
{
//删除在L中第i个数据元素e 并返回其值
int j, k = MAXSIZE - 1;
if(i < 1 || i > ListLength(L))
return false;
for(j = 1; j < i; j++) //移动 i- 1 个元素
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
*e = L[j].data;
Free(L,j);
return true;
}

void Free(SLinkList space,int k)
{
//将下标为k的空闲结点回收到备用链表
space[k].cur = space[0].cur; //回收结点的“游标”指向备用链表的第一个结点
space[0].cur = k; //备用链表的头结点指向新的收点
}

程序执行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: