新手笔记:约瑟夫算法

一群人围成一圈,选定一个数,从第一个人数,数到那个数的时候,对应的那个人紫砂,然后把西内的人挪走,空下来的位置接上,然后重新开始数,循环下去

链表


链表是一个循环单链表,给定一个数字让链表初始化,再给一个数字来算每到第几个节点就删除对应的节点,然后被删节点的前一个节点与后一个节点连接,循环下去

代码

节点类型

struct ListNode
{
    int L_num;
    ListNode* next;
 
    ListNode() :L_num(0), next(nullptr) {}
    ListNode(int num) :L_num(num), next(nullptr) {}
}; //节点类型

 链表初始化,显示,已经执行约瑟夫算法的函数

ListNode* initialList(int num)      //初始化链表,参数为节点数量
{
    ListNode* head = nullptr;
    ListNode* tail = nullptr;
    for (int i = 1; i <= num; i++)
    {
        if (!head)   //如果没有表头,则给head头指针一个指向新建的第一个节点
        {
            head = tail = new ListNode(i);
        }
        else   //已有表头,新建节点让tail给它们接上
        {
            tail->next = new ListNode(i);
            tail = tail->next;
        }
    }
    tail->next = head;
    return head;
}
 
void printList(ListNode* head)    //打印链表每个节点的数据
{
    ListNode* p = head;
    while (p->next != head)
    {
        cout << p->L_num << " -> ";
        p = p->next;
    }
    cout << p->L_num << endl;
}
 
ListNode* suicideSquad(ListNode* head, int num, int n)  //进行约瑟夫算法,参数第一个为链表头指针,第二个是节点数量,第三个是删除第n的节点
{
    ListNode* p = head;
    if (n < 1)  //防止乱输入
    {
        cout << "都活了,再见" << endl;
        exit(0);
    }
    int m = num % n;  //用于在循环移动到删除的节点前一个
    while (p->next != p)
    {
        for (int i = 1; i < m; i++)
        {
            p = p->next;
        }
        ListNode* temp = p->next;   //节点删除再连接
        ListNode* q = temp->next;
        p->next = q;
        p = q;
        delete temp;
        temp = nullptr;
    }
    head = p;   //将删除后p的指针给head,不加head的指针指向的节点已经被删除和释放,访问会错误
    return head;  //返回head 
}

 main一些东西

void test()
{
    ListNode* head = nullptr;
    int num = 41;
    cout << "紫砂前" << endl;
    head = initialList(num);
    printList(head);
    cout << endl;
    cout << "紫砂后" << endl;
    head = suicideSquad(head, num, 3);
    printList(head);
}
 
 
int main()
{
    test();
    cin.get();
    return 0;
}


紫砂小队嗯嗯

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值