双向链表和循环链表并用
作者:互联网
双向链表和循环链表并用
双向链表使用前驱指针以及后继指针
循环链表就是尾指针指向头
约瑟夫环问题:n个人围成一个圈,指定一个数字v,从第一个人开始报数,每轮报到v的选手出局,由下一个人接着从头开始报,最后一个人是赢家。其中n>1,v>2。
下面是循环链表(单向)在约瑟夫环中的应用,测试数据只用了615,答案是546231,可能程序还有其他错误,望指正。
以下变量中:n是总人数,s是第几个人,最后一个程序默认s是1,v是指定数字即循环次数;
#include <stdio.h>
#include<malloc.h>
/*单向的话需要两个指针,双向的话,一个指针就够了*/
struct s{
int m;
struct s*next;};
int count=0;
struct s*create(int n)
{
struct s*p,*phead,*pend;
p=((struct s*)malloc(sizeof(struct s)));
p->m=count+1;
while(count<n)
{
if(count==0)
{
phead=p;
pend=p;
pend->next=NULL;
count ++;
}
else
{
pend->next=p;
pend=p;
pend->next=NULL;
count ++;
}
p=((struct s*)malloc(sizeof(struct s)));
p->m=count+1;
}
pend->next=phead;
return phead;
}
int main(void)
{
struct s*p,*p0;
int n,s,v,a[100],j,i;
scanf("%d%d%d",&n,&s,&v);
p=create(n);
p0=p;
for(i=0;i<(s+v-3);i++)
p0=p0->next;
p=p0->next;
a[j]=p->m;j++;
p0->next=p->next;
while(n>1)
{
i=0;
while(i<v-1){p0=p0->next;i++;}
p=p0->next;
a[j]=p->m;j++;
p0->next=p->next;
p=p0->next;
n--;
}
for(i=0;i<j;i++)
printf("%d ",a[i]);
}
下面是循环链表(双向)在约瑟夫环的应用,测试数据只用了615,答案是546231,程序可能还有其他错误,若有不当请指正
#include<stdio.h>
#include<malloc.h>
struct s
{
int m;
struct s*prior;
struct s*next;
};
int count=0;
struct s*create(int n)
{
struct s*p,*phead,*pend;
p=((struct s*)malloc(sizeof(struct s)));
p->m=count+1;
while(count<n)
{
if(count==0)
{
pend=p;
phead=p;
p->next=NULL;
p->prior=NULL;
count++;
}
else
{
pend->next=p;
p->prior=pend;
pend=p;
pend->next=NULL;
count ++;
}
p=((struct s*)malloc(sizeof(struct s)));
p->m=count+1;
}
pend->next=phead;
phead->prior=pend;
return phead;
}
int main(void)
{
int n,s,v,a[100]={0},j=0,i;
struct s*p;
scanf("%d%d%d",&n,&s,&v);
p=create(n);
while(n>0)
{
i=0;
while(i<v-1)
{ i++;
p=p->next;
}
a[j]=p->m;j++;
p->prior->next=p->next;
p->next->prior=p->prior;/*双向链表删除一个节点时,修改后继指针的时候也要把前驱指针给修改了*/
p=p->next;
n--;
}
for(i=0;i<j;i++)
{
printf("%d",a[i]);
}
}
下面是没有链表的循环程序,个人认为还比较简单,不用链表也没有十分繁琐,主要涉及到数组中的坐标问题,其余的不是很复杂
测试数据只有615,答案是546231,若有不当请指正
#include<stdio.h>
void del(int a[],int n,int i);
int main(void)
{
int n,s,m,i,j=0,c,t;
int a[100]={0},b[100]={0};
scanf("%d%d%d",&n,&s,&m);
t=n;
for(i=0;i<n;i++)
{
a[i]=i+1;
}
for(c=m+s-2;j<t;j++)
{
c=c%n;
b[j]=a[c];
del(a,t,c);
n--;
c=c+m-1;
}
for(i=0;i<t;i++)
{
printf("%2d\n",b[i]);
}
return 0;
}
void del(int a[],int n,int i)
{
for(;i<n-1;i++)
{
a[i]=a[i+1];
}
}
注,数组删除元素:
1.字符数组删除元素每次删除一个到了末尾让\0往上补,\0也不会显示出来,以此达到删除的目的
2.整形数组删除时示例如下
输入 12345678
删除45
得到结果(若全部输出)
为12367888,最后的数字一定会赘余,因此要控制输出元素个数
如果输出的元素个数为6,则为123678,可以达到删除元素的目的。
标签:count,struct,并用,next,链表,int,pend,双向 来源: https://blog.csdn.net/weixin_52205764/article/details/112746345