约瑟夫问题:
问题:用循环链表模拟约瑟夫问题,把41个人自杀的顺序标号输出。
实现代码:
//n个人围圈报数,报m出列,最后剩下的是几号?
#include<stdio.h>
#include<stdlib.h>
typedefstruct node
{
int data;
struct node *next;
}node;
node*creat(int n)
{
node *p = NULL, *head;
head = (node*)malloc(sizeof(node));//创建头结点head
p = head;//p指向当前结点的指针
node *s;
int i = 1;
if(0 != n)
{
while(i <= n)
{
s = (node *)malloc(sizeof(node));
s -> data = i++;//为循环链表初始化,第一个结点为1,第二个结点为2
p -> next = s;
p = s;
}
s -> next = head -> next;
}
free(head);
return s -> next;
}
intmain()
{
int n = 41;
int m = 3;
int i;
node *p = creat(n);//p指向第一个结点
node *temp;//temp为临时指针
m % = n;
while(p != p -> next)
{
for(i = 1; i <= m; i++)
{
p = p -> next;
}
printf(“%d->”, p ->next -> data);
temp = p -> next;//删除第m个结点
p -> next = temp ->next;
free(temp);
p = p -> next;
}
printf(“%d\n”, p -> data);
return 0;
}
循环链表的特点:
rear是否等于rear -> next为判断是否为空链表的条件
例题:实现两个线性表(a1,a2,…,an)和(b1,b2,…,bm)连接成一个线性表(a1,…,an,b1,…bm)的运算。
分析:
若在单链表或头指针表示的单循环链表上做这种链接操作,都需要遍历第一个链表,找到结点an,然后将结点b1链到an的后面,其执行时间是O(n)
若用尾指针表示的单循环链表实现,只需修改指针,无需遍历,执行时间是O(1)
实现代码:
//假设A,B为非空循环链表的尾指针
LinkLIstConnect (LinkList A, LinkList B)
{
LimkList p = A -> next;//保存A表的头结点位置
A -> next = B -> next -> next;//B表的开始结点链接到A表尾
free(B -> next);//释放B表的头结点
B -> next = p;
return B;//返回新循环表的尾指针
}
判断单链表中是否有环:
有环的定义是,链表的尾结点指向了链表中的某个结点
判断单链表是否有环的俩能中方法:
1、使用p、q两个指针,p总是向前走,q每次都从头开始走,对于每个结点,看p走的步数是否和q一样,
2、使用p、q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p == q,则存在环