早期语言没有c,更不用说java等一些高级语言。那么是怎么描述链表这种实现呢?这次以单链表的模拟为例,深究一下 静态链表 的实现。
按照之前单链表的性质,我们需要游标和数据。当然,每个元素都有下标(类似数组)
静态链表中,首节点和尾结点都没有数据(数据为空) 首节点的游标指向第一个含有数据为空的元素的下标。 最后一个节点的游标指向第一个含有数据(不为空)的元素的下标。 附一张截图
未使用的数组元素是备用链表,这里我们做最简单的初始化
string InitList(StaticList L){ for(int i=0;i<MAXSIZE-1;i++) L[i].cur = i+1; L[MAXSIZE-1].cur = 0; return "Create an initlist"; }比较简单,直接代码实现吧
// 返回L中元素的个数 int GetLength(StaticList L){ int num=0; int i = L[MAXSIZE-1].cur; while(i){ i = L[i].cur; num++; } return num; }怎么模拟new和delete 的操作?即:需要的时候申请,不需要的时候释放它呢?做到模拟链表内存操作。这时候,将所有未被使用和删除的用游标连接成一个备用链表 再插入的时候,取得备用链表第一个结点做为插入结点即可。
附截图
注意:我们访问是按照游标读取的,所以 读取顺序: 下标:数据(游标) 1:A(5)–>5:B(2)–>2:C(3)–>3:D(4)……
先实现获得空闲分量下标的函数
//获得空闲分量下标 int GetEmpty(StaticList L){ int i = L[0].cur;//获得第一个空闲游标对应下标 if ( L[0].cur) L[0].cur = L[i].cur;//将下标为i的元素的下一个分量作为备用链表首节点 return i ; }然后是插入代码
//实现第i个元素前面插入新的元素 string InsertList(StaticList L,int i,ElemType e) { int j,k,l; k = MAXSIZE - 1; if (i<1||i>GetLength(L)) return "Insert fail: index out of range"; j = GetEmpty(L);//空闲分量下标 if(j){ L[j].data = e; for(l = 1;l<=i-1;l++) k = L[k].cur; L[j].cur = L[k].cur;//取出来L[k].cur,存放在插入结点中 L[k].cur = j;//再将L[k].cur的下标变成 插入节点的index值 return "Inserted"; } return "Insert fail"; }假设我们删除index = 2 的元素,那么肯定要改变备用链表和index = 5 的元素的cur(让其cur变为3)。而index = 0 的首节点的cur也要从6变为 2,index = 2的cur也得改变。即:交换两者的cur(附截图)
//将下标为k的空闲结点回收到备用链表 void DeleteNode(StaticList L,int k){ L[k].cur = L[0].cur; L[0].cur = k; } //删除对应Node string DeleteList(StaticList L,int i){ int j,k; if(i<1 || i>GetLength(L)) return "Delete fail: index out of range"; k = MAXSIZE - 1; for(j=1;j<=i-1;j++) k = L[k].cur; j = L[k].cur;//要删除元素的下标 L[k].cur = L[j].cur;//将链表重新连接 DeleteNode(L,j); return "Deleted"; }这种链表主要针对不提供指针操作的变成语言实现的。但是也不能像指针那样灵活利用内存。但是空的数据,我们可以理解为垃圾内存(被释放掉了的)。最重要的是理解这种思想(水一波)。