本节知识来源于大话数据结构,代码基本上也是参考这本书,引用书上原文,对于早期的编程语言,没有指针的概念,怎么实现链表,静态链表的想法就是用数组来模拟指针,其实我感觉静态链表的思想很重要,而使用静态链表基本很少,比如并查集的思想我感觉就是静态链表的应用。
需要注意的是数组第一个和最后一个元素不存数据,其中下标为0的元素的cur存放备用链表的第一个结点的下标,其实就是第一个空闲元素的下标,而数组的最后一个元素的cur存放第一个有数值的元素的下标,最后一个元素相当于头结点。
其中数据结构的书上只有初始化,分配结点和回收结点的代码,如下:
void InitSLL(struct StaticLinkList *space){
int i;
for(i=0;i<MAXN-1;i++) space[i].cur=i+1;
space[MAXN-1].cur=0;
}
int MallocSLL(struct StaticLinkList *space){
int i=space[0].cur;
if(i){
space[0].cur=space[i].cur; //下标为0的cur始终指向有空闲的元素下标,而不是space[0].cur=i,指向下标为i的元素
}
return i;
}
void FreeSLL(int k,struct StaticLinkList *space){ //k是需要释放空间的下标,而非第k个元素
space[k].cur=space[0].cur;
space[0].cur=k;
}
插入和删除操作,代码如下:
int insertSLL(int i,int val,struct StaticLinkList *space){
if(i<1||i>ListLength(space)+1) return 0;
int j=MAXN-1;
int k;
int t=MallocSLL(space);
if(j){
space[t].data=val;
for(k=1;k<=i-1;k++){
j=space[j].cur;
}
space[t].cur=space[j].cur;
space[j].cur=t;
return 1;
}
return 0;
}
int deleteSLL(int i,struct StaticLinkList *space){
if(i<1||i>ListLength(space)) return 0;
int j=MAXN-1,k;
for(k=1;k<=i-1;k++) j=space[j].cur;
k=space[j].cur;
space[j].cur=space[k].cur;
FreeSLL(k,space);
return 1;
}
另外还把数据结构书上的例子顺带实现了下,就是求(A-B)U(B-A),代码如下:
void difference(struct StaticLinkList *space){
InitSLL(space);
int s=MAXN-1,r,p,k;
r=s;
int m,n,i,j;
printf("输入两个集合的长度:");
scanf("%d%d",&m,&n);
for(j=0;j<m;j++){
i=MallocSLL(space);
scanf("%d",&space[i].data);
space[r].cur=i;
r=i;
}
space[r].cur=0;
display(space);
for(i=0;i<n;i++){
int tmp;
scanf("%d",&tmp);
p=MAXN-1;
k=space[p].cur;
while(k!=space[r].cur&&space[k].data!=tmp){
p=k;
k=space[k].cur;
}
if(k==space[r].cur){ //未出现重复,插入
j=MallocSLL(space);
space[j].data=tmp;
space[j].cur=space[r].cur;
space[r].cur=j;
}
else{ //出现重复,删除
space[p].cur=space[k].cur;
FreeSLL(k,space);
if(r==k) r=p;
}
}
display(space);
}
总的代码如下:
#include <stdio.h>
#include <stdlib.h>
#define MAXN 1000
struct StaticLinkList{
int data;
int cur;
};
void InitSLL(struct StaticLinkList *space){
int i;
for(i=0;i<MAXN-1;i++) space[i].cur=i+1;
space[MAXN-1].cur=0;
}
int MallocSLL(struct StaticLinkList *space){
int i=space[0].cur;
if(i){
space[0].cur=space[i].cur;
}
return i;
}
void FreeSLL(int k,struct StaticLinkList *space){
space[k].cur=space[0].cur;
space[0].cur=k;
}
int ListLength(struct StaticLinkList *space){
int i=space[MAXN-1].cur,j=0;
while(i){
i=space[i].cur;
j++;
}
return j;
}
void display(struct StaticLinkList *space){
int i=space[MAXN-1].cur;
while(i){
printf("%d ",space[i].data);
i=space[i].cur;
}
printf("\n");
}
int insertSLL(int i,int val,struct StaticLinkList *space){
if(i<1||i>ListLength(space)+1) return 0;
int j=MAXN-1;
int k;
int t=MallocSLL(space);
if(j){
space[t].data=val;
for(k=1;k<=i-1;k++){
j=space[j].cur;
}
space[t].cur=space[j].cur;
space[j].cur=t;
return 1;
}
return 0;
}
int deleteSLL(int i,struct StaticLinkList *space){
if(i<1||i>ListLength(space)) return 0;
int j=MAXN-1,k;
for(k=1;k<=i-1;k++) j=space[j].cur;
k=space[j].cur;
space[j].cur=space[k].cur;
FreeSLL(k,space);
return 1;
}
void difference(struct StaticLinkList *space){
InitSLL(space);
int s=MAXN-1,r,p,k;
r=s;
int m,n,i,j;
printf("输入两个集合的长度:");
scanf("%d%d",&m,&n);
for(j=0;j<m;j++){
i=MallocSLL(space);
scanf("%d",&space[i].data);
space[r].cur=i;
r=i;
}
space[r].cur=0;
display(space);
for(i=0;i<n;i++){
int tmp;
scanf("%d",&tmp);
p=MAXN-1;
k=space[p].cur;
while(k!=space[r].cur&&space[k].data!=tmp){
p=k;
k=space[k].cur;
}
if(k==space[r].cur){ //未出现重复,插入
j=MallocSLL(space);
space[j].data=tmp;
space[j].cur=space[r].cur;
space[r].cur=j;
}
else{ //出现重复,删除
space[p].cur=space[k].cur;
FreeSLL(k,space);
if(r==k) r=p;
}
}
display(space);
}
int main(int argc, char *argv[])
{
struct StaticLinkList space[MAXN];
difference(space);
return 0;
}
说实话,这块用的太少,代码也是边看书边敲,我感觉这个就是属于那种JAVA API知道有这种函数存在,不会的时候,然后查一查就行了的知识点。我只是贴了代码,过程没有书上写的详细,也没有配上应该需要的图片,最好还是看书吧。
未完待续:下一节 链表算法四之循环链表
如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步
文章转载请注明出处,请尊重知识产权