小孱弱弱又来打卡了,既上一篇的表继续,今天分享的数据结构相比于链表来说,不太常用,但是他们的重要性不言而喻,我们需要的是学习这种思想,走前辈走过的路,细品,这是对自己能力的考验,也是锻炼自己的好途径。你很棒,送给坚持为了梦想努力的人,是汗水就一定会有回报的!
首先是静态链表,现在比较流行的语言c呀,c++呀,Java呀要不就是有指针,c和c++,Java等高级语言有引用,可以方便的创建链表,但是杜宇一些比较古老的语言,像是basic、Fortran等,他们没有指针,链表的结构就没法实现了,这怎可能难到计算机前辈们,没有指针,就用其他的东西代替呗。
静态链表利用一个人游标cur来记住下一个结点的下表,不就轻松解决问题了,我们依然用结构体封装一下,设置一个数据域data和一个游标域cur。上代码:
//静态链表
//定义
typedef struct
{
int data;
int cur;
}Component ,StaticLinkList[MAXN];
int InitList(StaticLinkList space)
{
int i;
for(i=0;i<MAXN-1;i++)
{
space[MAXN-1].cur=i+1;
}
space[MAXN-1].cur=0;
}
//表长
int ListLength(StaticLinkList L)
{
int j=0;
int i=L[MAXN-1].cur;
while(i)
{
i=L[i].cur;
j++;
}
return j;
}
//增
int Malloc_SSL(StaticLinkList space)//m空间
{
int i=space[0].cur;
if(space[0].cur)
space[0].cur=space[i].cur;
return i;
}
int LinkInsert(StaticLinkList L,int i,int e)
{
int j,//空位
k, //i-1位
l;//i-1 位
k=MAXN-1;
if(i<1||i>L[0].cur)
return false;
j=Malloc_SSL(L);
if(j)
L[i].data=e;
for( l=1;l<=i-1;l++)
{
k=L[k].cur;//i-1元素游标
}
L[j].cur=L[k].cur;//i-1位的元素 赋值给空位的游标
L[k].cur=j;//空位的游标赋值给i-1位的游标
return true;
}
//删
void Free_SSL(StaticLinkList space,int k)
{
space[k].cur=space[0].cur;
space[0].cur=k;
}
int ListDelete(StaticLinkList L,int i)
{
int j,k;
if(i<1||i>ListLength(L))
return false;
k=MAXN-1;
for(j=1;j<=i-1;j++)
k=L[k].cur;
j=L[k].cur;
L[k].cur=L[j].cur ;
Free_SSL(L,j);
return true;
}
我们初始化静态链表时,将每个结点的游标域指向下一个结点的下标,头结点游标指向最后一个数据元素的下一个结点,表尾巴记住头结点的下标0,要遍历整表比较容易,我就不多说了,增删元素,这里就不同于其他表了重点哦:增操作,插入之前,我们要先给他把位置留出来,怎么留呢?
首先首节点记住的游标+1,意味着元素加一,我们直接把向尾巴元素一放,把我们要插入位置的前驱,这在这个结点的游标改成最后一个元素节点的下标,把最后元素节点的游标,改成插入位置的后继的下标,然后呢把插入位置的游标改成最后元素节点的下标,ok,完美结束,实现了不需要移动大量元素,实现插入操作,其实就是利用了间接指针,不得不佩服前辈的智慧!!至于删除操作就很简单了~就不多说了。
对于静态链表,我们基本不会用到了,但是它的思想十分精巧,值得学习!!!
下面是循环链表和双向链表:
循环链表,顾名思义,原本的尾指针指向空NULL,我们让尾指针指向头指针,就让一个单链表循环起来了,为了方便遍历,我们通常设置一个指针rear指向尾结点,这样我们无论是从头遍历,还是遍历到一半或者从尾巴遍历都很方便了,有一个出名的实例-约瑟夫死亡游戏,有兴趣可以百度一下看看,以后有机会我会发一篇约瑟夫死亡圈游戏的。回到正题,双向链表,我们对于单链表的查找,时间复杂度不满意,希望能更快的查找,又是我们有引入一个指向结点前去前驱的指针域prior,这样等同于头尾都可以当头,也可以当尾巴,对于中间一个结点,无论是向前遍历,还是向后遍历,都十分方便。具体请看代码实现。
由于思想比较好理解,上代码:
//循环链表
/* 在为节点上的指针域指向头结点,降低查找时间复杂度
例:
合并操作 (near 是指向为节点的指针————尾指针)
p=rearA->next;//保存表A的头结点
rearA->next=nearB->next->next;//B表的头结点的下一个结点
q=rearB->next;
nearB->next=p;
free(q);
*/
//双向链表 //空间换时间
typedef struct DulNode
{
int data;
struct DulNode* prior;
struct DulNode* next;
} DulNode ,*DulLinkList;
//增
s->prior=p;
s->next=p->next;
p->next->prior=s;
p->next=s;
//删
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);