2.2链表-约瑟夫环问题-两种解决思想

课件代码: 

#include<iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int  No;              /*游戏者的编号*/
    int  Pwd;    /*游戏者的密码*/
    struct node *next;
}LNode,*LinkList;

LinkList  create_list(int n)/*用尾插法创建一个结点数为n的单循环链表,返回值为尾结点的指针*/
{
    LinkList p,r;
    int i;
    /*创建循环链表的第一个结点*/
    p = (LinkList)malloc(sizeof(LNode));
    if (p==NULL)
    {
        printf("memory allocation error!\n");
        return NULL;
    }
    printf("input password:");
    scanf("%d",&(p->Pwd));
    p->No = 1;
    p->next = p;
    r = p;
    //创建循环链表的其余n-1个结点
    //返回表尾结点指针;
    //LinkList r, p;   int i;
    //创建循环链表的第一个结点,并令head和r指向该结点;
    for(i = 2; i <= n; i++)  /*创建循环链表的其余n-1个结点*/
    {
        p = (LinkList)malloc(sizeof(LNode));
        if (!p)
        {
            printf("memory allocation error!\n");
            return NULL;
        }
        scanf("%d",&(p->Pwd));
        p->No = i;
        p->next = r->next;
        r->next = p;
        r = p;
    }/*for*/
    return r;
}/* create_list */

void playing(LinkList tail, int n, int m)
{
    LinkList pre, p;
    int k;
    m = m % n ? m % n : n;
    pre = tail;
    p = tail -> next;
    k = 1;
    while (n > 1)  /*圈中多于1个人时循环*/
    {
        if (k == m)   /*数到需要出圈的人(结点)*/
        {
            printf("%d ", p->No); /*p指向的结点为需要删除的结点*/
            pre -> next = p -> next;
            n--;
            m = p -> Pwd % n ? p -> Pwd % n : n;
            free(p);
            p = pre -> next;
            k = 1;
        }
        else
        {
            k++;
            pre = p;
            p = p->next;
        }
    }/*while*/
    printf("%d ", p->No);
}/*playing*/
void output_list(LinkList Out)
{
    printf("##%d\n", Out->No);
}
int main(void)
{
    LinkList tail;
    int n, it;
    printf("input the number of players and initial password:");
    scanf("%d %d",&n, &it);
    tail = create_list(n);   	  /*创建单循环链表*/
    if (tail)
    {
        output_list(tail);  /*输出循环链表中结点的信息*/
        playing(tail, n, it);
    }
    return 0;
}

/*
7 5
3 8 1 22 4 9 15

*/


讲义代码:

#include<iostream>
using namespace std;
const int N = 20;
typedef struct node  //定义一个双向链表
{
    int id;
    struct node *next; //后继指针
    struct node *pre; //前驱指针
} Node,*pNode;
pNode RingConstruct(int n)
{
    int i;
    pNode head, p, q;
    head = (pNode)malloc(sizeof(Node)); //建立第一个结点
    head->id = 1; //其ID 为1
    p = head;
    for ( i = 2; i<=n; i++) //循环n-1 ,将剩余的n-1 个元素赋值,入队列
    {
        q = (pNode)malloc(sizeof(Node));
        q->id = i;
        p->next = q;
        q ->pre = p;
        p = p->next;
    }
    p->next = head;
    head->pre = p;
    return head;
}
/*传入报数的次数序号,返回此次报数的上限*/
int boundMachine(int order)
{
    int boundList[4] = { 3, 5, 7, 13 };
    return boundList[(order - 1) % 4];
}
pNode count(pNode first, int bound)  //返回当前趟的起始结点,bound 参数由
{
//boundMachine 提供
    pNode q;
    q = first;
    for (int i = 2; i <= bound; i++)
    {
        q = q->next;
    }
    return q;
}
/*将currentNode 从环中删除,并返回被删除结点的下一结点*/
pNode removeNode(pNode currentNode)
{
    pNode first = currentNode->next; //当前删除结点的后继是下一趟的起始结点
    currentNode->pre->next = currentNode->next;
    first->pre = currentNode->pre;
    cout << currentNode->id << " ";
    free(currentNode);
    return first;
}
int main()
{
    pNode first, toRemove; //first 为每趟的起始结点,toRemove 为要删除结点,通过
//函数removeNode 提供下一趟起始地址
    int i;
    first = RingConstruct(N);
    for (int i = 1; i <= N; i++)
    {
        toRemove = count(first, boundMachine(i));
        first = removeNode(toRemove);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42137874/article/details/107695438