其他分享
首页 > 其他分享> > 双向链表和循环链表并用

双向链表和循环链表并用

作者:互联网

双向链表和循环链表并用

双向链表使用前驱指针以及后继指针
循环链表就是尾指针指向头
约瑟夫环问题: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