双向循环链表
节点类型与双链表的节点类型完全相同双向循环链表的操作也与双链表的操作基本一致。
例题
将自然数一到N按由小到大的顺序沿顺时针方向围成一个圈,然后以一为起点先沿顺时针方向数到第N个数将其划去,再沿逆时针方向数到第K个数将其滑去,重复上述操作直到剩下一个数为止,问最后剩下的是哪个数。(用带头节点双向循环链表实现。)
静态链表
图示:
适用情况:
无法实现上述的链式存储但可以借用一维数组来实现的情况可以使用。
优点:
线性表的插入和删除操作时不需要移动元素,仅需要修改指针游标就行。具有链式存储的主要优点
主要函数:
1、定义结构
代码
#include<stdio.h> typedef int Element; #define Maxsize 100 //定义结构 typedef struct { Element date; int cur; }StaLink[Maxsize];
注意:
date数据,cur游标(看作指针也可以),StaLink[i](i即为下标)
2、初始化:(申请空间)
建立一个空的静态链表space(将一维数组space中各分量炼成一个备用链表零表示空指针根据当前地图)
理解:
代码:
//初始化 void creatLink(StaLink space){ int i=0; for(i=0;i<Maxsize-1;i++){ space[i].cur=i+1; space[Maxsize-1].cur=0; } }
3、获取结点函数:
从备用链表上获取一个新的结点,如果备用连表已经空了,获取节点的操作失败
理解:
感觉就是把头结点的next的结点的下标返回【不太理解】
通过看第5个建立静态表可以知道:
4、回收结点函数:(释放)
将从链表中删除的结点插入到备用链表中的头结点之后
5、建立静态表:
建立一个含有n个节点的静态链表head
//建立静态链表 int createlink(StaLink space,int n){ int k,head,s; //把头head申请出来 k=head=allocnode(StaLink space); for(int i=0;i<=n;i++){ //循环把结点一个一个申请出来 s=allocnode(StaLink space); scanf("%d",&space[s].date); space[k].cur=s k=s;//因为新的s就是下一个循环的头 } space[k].cur=0; return head;//返回即为头结点的下标 }
6、求表长:
计算静态链表head中数据元素的个数
//求表长 int getlen(StaLink space,int head) { int i=0,s; s=space[head].cur; while(s!=0){ s=space[s].cur; i++; } return i; }
7、取元素:
取出静态链表head中的第i个结点的元素值
//取元素:取出静态链表head中的第i个结点的元素值 int getdate(StaLink space,int i,int head,Element *e){ //此时多加一个Element,而不是直接返回, //可以理解为Element数据类型不一定为int,方便后续修改和使用 int j=0,s,k=head; //补加k=head; s=space[head].cur; //如何考虑i不在范围内 ? if(i>getlen(StaLink,head)||i<1)return 0; while(j<i&&k!=0) //补加 k!=0 {s=space[s].cur; j++;} if(k==0)return 0; //补加 *e=space[j].date; return 1; }
8、定位:
确定静态链表head中第1个值为x的结点的位置
//定位:确定静态链表head中第1个值为x 的结点的位置 int locate(StaLink space,int head,Element x){ //遍历,比较数据 int k; k=space[head].cur; while(space[k].date!=x&&k!=0){ k=space[k].cur; } while(k==0)return 0; return k; }
9、插入:
在静态链表head的第i个结点之前插入一个值为x的新结点
10、删除:
讲静态链表head中的第i个结点
11、输出:
从头结点开始,依次输出静态链表head中的所有元素值。