数据结构与算法-表(静态链表 循环链表 双向链表)

小孱弱弱又来打卡了,既上一篇的表继续,今天分享的数据结构相比于链表来说,不太常用,但是他们的重要性不言而喻,我们需要的是学习这种思想,走前辈走过的路,细品,这是对自己能力的考验,也是锻炼自己的好途径。你很棒,送给坚持为了梦想努力的人,是汗水就一定会有回报的!
首先是静态链表,现在比较流行的语言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);
	

猜你喜欢

转载自blog.csdn.net/weixin_47644373/article/details/106148861