您的位置:首页 > 理论基础 > 数据结构算法

数据结构笔记:3.5 静态链表/游标实现法

2020-07-15 05:30 162 查看

1、概念
首先让数组的元素都是由两个数据域组成,data和cursor。也就是说,数组的每个下标都对应一个data和一个cursor。数据与data,用来存放数据元素,也就是需要处理的数据;而cursor相当于单链表中的next指针,存放该元素的后继在数组中的下标,通常把cursor叫做游标。
用数组描述的链表叫做静态链表,又叫做游标实现法。

2、具体实现代码
(1)静态链表的数据存储结构

typedef struct StaticLinkedList
{/*静态链表的数据存储*/
/*StaticLinkedListArray[0]相当于备用链表的头结点(将为静态链表中未储存数据的部分视为备份链表),不用于存储需要使用的数据,cursor存储静态链表的备用空表的第一个结点的下标(即第一个没有存储数据的结点的下标),当cursor=0时,表示该静态链表已满*/
/*StaticLinkedListArray[MAXSIZE-1]也不存放数据,相当于该静态链表的头结点(存储数据部分),data存储静态链接表的长度(不包括第一个结点),cursor存放数组中第一个数据所在位置的下标(不是头结点),若cursor=0则表示该链表为空*/
/*数组的最后一个结点StaticLinkedListArray[MAXSIZE-1]也不存放数据,该结点的cursor存放数组中第一个数组所在的结点的下标(不是头结点)*
/*静态链表中最后一个数据所在的位置的cursor=0,即指向备用链表的头结点*/
ElemType data;
int cursor;/*存放下一个数据的下标*/
}StaticLinkedList, StaticLinkedListArray[MAXSIZE];

(2)初始化静态链表

void Initialization(StaticLinkedListArray L)
{/*初始化静态链表*/
int i = 1;
while (i < MAXSIZE)
L[i-1].cursor = i++;
L[MAXSIZE - 1].data = 0;/*初始化静态链表的数据个数*/
L[MAXSIZE - 1].cursor = 0;/*初始化静态链表的头结点的指向*/
}

(3)分配空间

int AllocateSpace(StaticLinkedListArray L)
{/*分配空间,返回下标*/
if (L[MAXSIZE-1].data >=MAXSIZE-2)
return ERROR;/*当静态链表已满时,返回错误*/
int j = L[0].cursor;/*获取备用链表的第一个下标*/
L[0].cursor = L[j].cursor;/*备用链表头结点存放的下标后移一位*/
return j;
}

(4)输出静态链表

void Display(StaticLinkedListArray L)
{/*输出静态链表的长度及数据*/
if (L[MAXSIZE - 1].data == 0)
printf("静态链表为空!\n");
else
{
int i = L[MAXSIZE-1].cursor;/*获取第一个数据的下标*/
printf("静态链表的长度为:%d\n静态链表中的数据为:", L[MAXSIZE - 1].data);
while (i != 0)
{/*当输出到最后一个数据,即cursor==0后,退出循环*/
printf("%3d", L[i].data);
i = L[i].cursor;/*获取下一个数据的下标*/
}
putchar('\n');
}
}

(5)分配空间

int AllocateSpace(StaticLinkedListArray L)
{/*分配空间,返回下标*/
if (L[MAXSIZE-1].data >=MAXSIZE-2)
return ERROR;/*当静态链表已满时,返回错误*/
int j = L[0].cursor;/*获取备用链表的第一个下标*/
L[0].cursor = L[j].cursor;/*备用链表头结点存放的下标后移一位*/
return j;
}

(6)初始化静态链表数据

void InitializationData(StaticLinkedListArray L)
{/*输入初始化静态链表的数据*/
int i=1;
L[MAXSIZE - 1].cursor = 1;
printf("请输入初始化创建数据的数目:");
scanf_s("%d", &L[MAXSIZE-1].data);
while (i <= L[MAXSIZE - 1].data)
{
printf("请输入第%d个数据:", i );
scanf_s("%d", &L[i].data);
i++;
}
L[i - 1].cursor = 0;
L[0].cursor = i;
}

(7)插入数据:单个数据插入

int Interposition(StaticLinkedListArray L,int i,ElemType e)
{/*插入单个数据:i为需要插入的位置,e为需要插入的数据*/
if ((i > L[MAXSIZE - 1].data + 1) || (L[MAXSIZE - 1].data >= MAXSIZE - 2))
return ERROR;/*若果插入位置超出静态链表长度或者超出静态链表的空间,则返回错误*/
int k,j=1;
k = MAXSIZE - 1;/*获取头结点的下标*/
++L[MAXSIZE - 1].data;/*静态链表长度加1*/
while (j < i)/*查询第i-1位置上的数据的下标*/
{
k = L[k].cursor;
j++;
}
j = AllocateSpace(L);/*获取空位置的下标*/
L[j].data = e;
L[j].cursor = L[k].cursor;
L[k].cursor = j;
return OK;
}

(8)插入数据:批量插入数据

int InterpositionS(StaticLinkedListArray L)
{/*批量插入数据*/
int number,k,i=0,e;/*number 输入数据的数目;k 插入的位置;e 插入的数据*/
printf("请输入需要插入数据的数目:");
scanf_s("%d", &number);
if ((L[MAXSIZE].data + number) > MAXSIZE - 2)
return ERROR;/*当所剩空间不够时,返回错误*/
printf("请输入需要插入的位置:");
scanf_s("%d", &k);
while (i < number)
{
printf("请输入需要插入的第%d个数据:", i+1);
scanf_s("%d", &e);
Interposition(L, k + i, e);
i++;
}
return OK;
}

(9)释放空间

int FreeSpace(StaticLinkedListArray L,int k)
{/*释放空间*/
if (k > L[MAXSIZE].data)
return ERROR;
L[k].cursor = L[0].cursor;
L[0].cursor = k;
return OK;
}

(10)删除数据:按数据删除

int DeleteData(StaticLinkedListArray L, ElemType e)
{/*删除数据:按数据删除*/
int k = MAXSIZE-1,kk;
while (L[L[k].cursor].data != e && L[L[k].cursor].cursor != 0)
k = L[k].cursor;
if (L[L[k].cursor].data == e)
{
--L[MAXSIZE-1].data;
kk = L[k].cursor;
L[k].cursor = L[kk].cursor;
FreeSpace(L, kk);
return OK;
}
return ERROR;
}

(11)删除数据:按位置删除

int DeleteAddress(StaticLinkedListArray L, int k)
{/*删除数据:按位置删除*/
if (k > L[MAXSIZE - 1].data)
return ERROR;
int i = 1,t,tt;
--L[MAXSIZE - 1].data;/*链表长度减1*/
t = MAXSIZE - 1;/*获取头结点的下标*/
while (i < k)/*寻找需要删除的位置之前的那一个位置*/
{
t = L[t].cursor;
i++;
}
tt = L[t].cursor;/*获取删除位置的下标*/
L[t].cursor = L[tt].cursor;
FreeSpace(L,tt);
return OK;
}

(12)查询数据:按值查询

int ReferData(StaticLinkedListArray L, ElemType e)
{/*查询数据:按值查询*/
int i = L[MAXSIZE - 1].cursor;
while (L[i].data != e && L[i].cursor != 0)
i = L[i].cursor;
if (L[i].data == e)
{
printf("%d的下标为:%d\n", e, i);
return L[i].data;
}
printf("不存在该数据!\n");
return ERROR;
}

(13)查询数据:按位置查询

int ReferAddress(StaticLinkedListArray L, int k)
{/*查询数据:按位置查询*/
if (k > L[MAXSIZE - 1].data)
{
printf("不存在该位置!\n");
return ERROR;
}
int i = 1,j;
j = L[MAXSIZE - 1].cursor;
while (i++ < k)
j = L[j].cursor;
printf("静态链表第%d个位置的下标为:%d\t数据为:%d\n",k,j, L[j].data);
return L[j].data;
}

(14)测试代码(编译环境:Visual Studio 2017)

#include<stdio.h>

#define OK 1
#define ERROR 0
#define MAXSIZE 27
typedef int ElemType;

typedef struct StaticLinkedList
{/*静态链表的数据存储*/
/*StaticLinkedListArray[0]相当于备用链表的头结点(将为静态链表中未储存数据的部分视为备份链表),不用于存储需要使用的数据,cursor存储静态链表的备用空表的第一个结点的下标(即第一个没有存储数据的结点的下标),当cursor=0时,表示该静态链表已满*/
/*StaticLinkedListArray[MAXSIZE-1]也不存放数据,相当于该静态链表的头结点(存储数据部分),data存储静态链接表的长度(不包括第一个结点),cursor存放数组中第一个数据所在位置的下标(不是头结点),若cursor=0则表示该链表为空*/
/*数组的最后一个结点StaticLinkedListArray[MAXSIZE-1]也不存放数据,该结点的cursor存放数组中第一个数组所在的结点的下标(不是头结点)*
/*静态链表中最后一个数据所在的位置的cursor=0,即指向备用链表的头结点*/
ElemType data;
int cursor;/*存放下一个数据的下标*/
}StaticLinkedList, StaticLinkedListArray[MAXSIZE];
void Initialization(StaticLinkedListArray L)
{/*初始化静态链表*/
int i = 1;
while (i < MAXSIZE)
L[i-1].cursor = i++;
L[MAXSIZE - 1].data = 0;/*初始化静态链表的数据个数*/
L[MAXSIZE - 1].cursor = 0;/*初始化静态链表的头结点的指向*/
}
void Display(StaticLinkedListArray L)
{/*输出静态链表的长度及数据*/
if (L[MAXSIZE - 1].data == 0)
printf("静态链表为空!\n");
else
{
int i = L[MAXSIZE-1].cursor;/*获取第一个数据的下标*/
printf("静态链表的长度为:%d\n静态链表中的数据为:", L[MAXSIZE - 1].data);
while (i != 0)
{/*当输出到最后一个数据,即cursor==0后,退出循环*/
printf("%3d", L[i].data);
i = L[i].cursor;/*获取下一个数据的下标*/
}
putchar('\n');
}
}
int AllocateSpace(StaticLinkedListArray L)
{/*分配空间,返回下标*/
if (L[MAXSIZE-1].data >=MAXSIZE-2)
return ERROR;/*当静态链表已满时,返回错误*/
int j = L[0].cursor;/*获取备用链表的第一个下标*/
L[0].cursor = L[j].cursor;/*备用链表头结点存放的下标后移一位*/
return j;
}void InitializationData(StaticLinkedListArray L)
{/*输入初始化静态链表的数据*/
int i=1;
L[MAXSIZE - 1].cursor = 1;
printf("请输入初始化创建数据的数目:");
scanf_s("%d", &L[MAXSIZE-1].data);
while (i <= L[MAXSIZE - 1].data)
{
printf("请输入第%d个数据:", i );
scanf_s("%d", &L[i].data);
i++;
}
L[i - 1].cursor = 0;
L[0].cursor = i;
}
int Interposition(StaticLinkedListArray L,int i,ElemType e)
{/*插入单个数据:i为需要插入的位置,e为需要插入的数据*/
if ((i > L[MAXSIZE - 1].data + 1) || (L[MAXSIZE - 1].data >= MAXSIZE - 2))
return ERROR;/*若果插入位置超出静态链表长度或者超出静态链表的空间,则返回错误*/
int k,j=1;
k = MAXSIZE - 1;/*获取头结点的下标*/
++L[MAXSIZE - 1].data;/*静态链表长度加1*/
while (j < i)/*查询第i-1位置上的数据的下标*/
{
k = L[k].cursor;
j++;
}
j = AllocateSpace(L);/*获取空位置的下标*/
L[j].data = e;
L[j].cursor = L[k].cursor;
L[k].cursor = j;
return OK;
}
int InterpositionS(StaticLinkedListArray L)
{/*批量插入数据*/
int number,k,i=0,e;/*number 输入数据的数目;k 插入的位置;e 插入的数据*/
printf("请输入需要插入数据的数目:");
scanf_s("%d", &number);
if ((L[MAXSIZE].data + number) > MAXSIZE - 2)
return ERROR;/*当所剩空间不够时,返回错误*/
printf("请输入需要插入的位置:");
scanf_s("%d", &k);
while (i < number)
{
printf("请输入需要插入的第%d个数据:", i+1);
scanf_s("%d", &e);
Interposition(L, k + i, e);
i++;
}
return OK;
}
int FreeSpace(StaticLinkedListArray L,int k)
{/*释放空间*/
if (k > L[MAXSIZE].data)
return ERROR;
L[k].cursor = L[0].cursor;
L[0].cursor = k;
return OK;
}
int DeleteData(StaticLinkedListArray L, ElemType e)
{/*删除数据:按数据删除*/
int k = MAXSIZE-1,kk;
while (L[L[k].cursor].data != e && L[L[k].cursor].cursor != 0)
k = L[k].cursor;
if (L[L[k].cursor].data == e)
{
--L[MAXSIZE-1].data;
kk = L[k].cursor;
L[k].cursor = L[kk].cursor;
FreeSpace(L, kk);
return OK;
}
return ERROR;
}
int DeleteAddress(StaticLinkedListArray L, int k)
{/*删除数据:按位置删除*/
if (k > L[MAXSIZE - 1].data)
return ERROR;
int i = 1,t,tt;
--L[MAXSIZE - 1].data;/*链表长度减1*/
t = MAXSIZE - 1;/*获取头结点的下标*/
while (i < k)/*寻找需要删除的位置之前的那一个位置*/
{
t = L[t].cursor;
i++;
}
tt = L[t].cursor;/*获取删除位置的下标*/
L[t].cursor = L[tt].cursor;
FreeSpace(L,tt);
return OK;
}
int ReferData(StaticLinkedListArray L, ElemType e)
{/*查询数据:按值查询*/
int i = L[MAXSIZE - 1].cursor;
while (L[i].data != e && L[i].cursor != 0)
i = L[i].cursor;
if (L[i].data == e)
{
printf("%d的下标为:%d\n", e, i);
return L[i].data;
}
printf("不存在该数据!\n");
return ERROR;
}
int ReferAddress(StaticLinkedListArray L, int k)
{/*查询数据:按位置查询*/
if (k > L[MAXSIZE - 1].data)
{
printf("不存在该位置!\n");
return ERROR;
}
int i = 1,j;
j = L[MAXSIZE - 1].cursor;
while (i++ < k)
j = L[j].cursor;
printf("静态链表第%d个位置的下标为:%d\t数据为:%d\n",k,j, L[j].data);
return L[j].data;
}
void Menu()
{
printf("程序功能菜单:\n0:菜单\n1:初始化静态链表及输入初始化数据\n2:插入数据\n3:输出数据\n4:删除数据:按数据删除\n"
"5:删除数据:按位置删除\n6:查询数据:按数据查询\n7:查询数据:按位置查询\n8:退出程序\n");
}

int main(void)
{
int i = 0,e;
StaticLinkedListArray L;
while (i != 8)
{
switch (i)
{
case 0:
Menu();
break;
case 1:
Initialization(L);
printf("初始化成功!\n");
InitializationData(L);
Display(L);
break;
case 2:
InterpositionS(L);
Display(L);
break;
case 3:
Display(L);
break;
case 4:
printf("请输入需要删除的数据:");
scanf_s("%d", &e);
DeleteData(L, e);
Display(L);
break;
case 5:
printf("请输入需要删除的位置:");
scanf_s("%d", &e);
DeleteAddress(L, e);
Display(L);
break;
case 6:
printf("请输入需要查询的数据:");
scanf_s("%d", &e);
ReferData(L, e);
break;
case 7:
printf("请输入需要查询的位置:");
scanf_s("%d", &e);
ReferAddress(L, e);
break;
default:
printf("不存在该功能选项!\n");
break;
}
printf("请输入需要执行的功能选项:");
scanf_s("%d", &i);
}
printf("感谢您的使用!\n");
return 0;
}

运行结果

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