单向循环链表
如图所示当最后一个节点当next 指向首元节点时,单向链表就变成了单向循环链表
首先我们定义一个数据结构用于存储数据
typedef int ElemType;
typedef struct Node {
ElemType data;
struct Node * next;
}Node;
typedef struct Node * LinkList;
单向链表的创建 (根据idx 选择插入位置),创建单向循环链值得注意当是
- 1.第一次创建
- 2.已经创建,新增数据
代码如下:
// 单向循环链表 第idx 位置插入数据
Status CreateLinkList (LinkList *L ,int idx , ElemType e){
if ( *L == NULL) {
(*L) = (LinkList)malloc(sizeof(Node));
if(!*L) return ERROR;
(*L)->data = e;
(*L)->next = *L;
}else{
LinkList p,temp;
p = *L;
int j ;
// 找到最后一个节点
for (j = 1; j < idx && p->next != *L; j++ ,p = p->next);
if (j< idx) {
printf("idx越界超出插入范围!\n");
return ERROR;
}
// p 为当前要插入的节点 j 为当前要插入的节点位置
temp = (LinkList)malloc(sizeof(Node));
if (!temp) return ERROR;
temp->data = e;
temp->next = p->next;
p->next = temp;
}
return SUCCESS;
}
输出结果为 1-100, 当然 CreateLinkList 支持以任何节点插入数据
单向循环链表单删除
删除节点单时候, (根据idx 选择删除位置),也有一些值得注意当是
- 1.是否为首元节点
- 2.删除节点的时候要先接收所要删除节点的next,单链会丢失
代码如下:
// 单向循环链表 第idx 位置删除节点
LinkList deleteLinkList (LinkList *L ,int idx ){
LinkList p ,temp;
p = *L
int j ;
if (p == NULL) return NULL;
if(idx == 1){
// 如果删除到只剩下首元结点了,则直接将*L置空;
if((*L)->next == (*L)){
(*L) = NULL;
return SUCCESS;
}
// 获取下最后一个
while (p->next != *L) {
p = p->next;
}
temp = *L;
*L = (*L)->next;
p->next = *L;
}else{
// 容错处理
for (j=1; j<idx && p->next != *L; j++,p= p->next) {
temp = p->next;
p->next = temp->next;
free(temp);
}
}
return p->next;
}
注意以上代码返回值为什么是个LinkList?,当然返回值是我们自己用于定义的,为什么返回LinkList 主要是下面我们将会用到,(解约瑟夫)
- 如题:有n个人,编号为1~n,从第一个人开始报数,从1开始报,报到m的人会死掉,然后从第m+1个人开始,重复以上过程。在死了n-1个人后,问最后一个人的编号是?
//约瑟夫解法
ElemType ysfList(LinkList *L ,int idx ){
LinkList p , temp;
p = *L;
int j ,sum;
if (p->next == *L) return (*L)->data;
// 容错处理 先求下总长度
for (sum = 1; p->next != *L; sum ++, p = p->next) ;
if (sum > 1){
j = (sum > 1)?(idx % sum):idx;
// 删除对应位置的节点,并返回next
temp = deleteLinkList(L ,j-1);
// printf("删除后下一次开始数的\n");
// ListTraverse(temp);
ysfList(&temp , idx);
}
return (*L)->data;
}
之后我们就可以随机输入看看效果了