【循环链表】28 循环链表ADT模板简单应用算法设计:约瑟夫环

本文介绍了如何使用C++模板设计循环链表的抽象数据类型,并实现约瑟夫环问题的算法。通过循环链表ADT,程序接收输入的人数、每个人持有的密码和随机数m,输出出圈的顺序。代码中定义了循环链表的节点结构,实现了增删查改等基本操作,并展示了如何解决约瑟夫环问题。
摘要由CSDN通过智能技术生成

问题描述 :

目的:使用C++模板设计循环链表的抽象数据类型(ADT)。并在此基础上,使用循环链表ADT的基本操作,设计并实现单链表的简单算法设计。

内容:

(1)请使用模板设计循环链表的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考网盘中的单链表ADT原型文件,自行设计循环链表的ADT。)

 

(2)ADT的简单应用:使用该ADT设计并实现循环链表应用场合的一些简单算法设计。

应用2:编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。现在给定一个随机数m>0,从编号为1的人开始,按顺时针方向1开始顺序报数,报到m时停止。报m的人出圈,同时留下他的密码作为新的m值,从他在顺时针方向上的下一个人开始,重新从1开始报数,如此下去,直至所有的人全部出列为止。请在使用循环链表ADT的基础上,设计一个算法求出圈的顺序(以编号表示)。限定人数至少为1.

参考函数原型:

template<class ElemType>

void Joseph(CirLinkList<ElemType> &A, int m);

 

//约瑟夫环专用结点类型

struct node{

    int number;

    int code;

};

 

输入说明 :

第一行:人数n

第二行:每个人所持的密码

第三行:给定的随机数m

输出说明 :

第一行:建立的循环链表的遍历结果(数据格式见测试数据范例)

空行

第三行:出圈的顺序(编号与编号之间以“->”分隔)

输入范例 :


3 8 1 22 4 9 15
5

输出范例 :

(1,3)->(2,8)->(3,1)->(4,22)->(5,4)->(6,9)->(7,15)

5->2->6->7->4->3->1

解题代码: 

// 循环链表.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <sstream>
#include <stack>
#include <map>
#include <ctime>
#include <array>
#include <set>
#include <list>
using namespace std;
template<class ElemType>
struct LinkNode
{
    ElemType data;
    LinkNode<ElemType>* next;
    LinkNode(LinkNode<ElemType>* ptr = NULL) 
    { 
        next = ptr;  //构造函数1,用于构造头结点
    }
    LinkNode(const ElemType& item, LinkNode<ElemType>* ptr = NULL) 
    {
        //构造函数2,用于构造其他结点   
        //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
        next = ptr;
        data = item;
    }
    //int getNum(){ return number; } //取得结点的序号 
    ElemType getData() 
    { 
        return data; //取得结点的数据域的值 
    }   
    void SetLink(LinkNode<ElemType>* link) 
    { 
        next = link; 
        //修改结点的next域 
    } 
    void SetLink(ElemType value) 
    { 
        data = value; 
        //修改结点的next域
    } 
};
//带头结点的循环单链表 

template<class ElemType>

class CirLinkList {
private:
    LinkNode<ElemType>* head;   // 头结点
    LinkNode<ElemType>* tail;   // 尾结点
public:
    //无参数的构造函数
    CirLinkList() 
    { 
        head = NULL;
        tail = NULL; 
    }
    CirLinkList(CirLinkList<ElemType>& List);//拷贝构造函数
    ~CirLinkList() 
    { 
        //析构函数
        del_clear();
    }
    LinkNode<ElemType>* front(LinkNode<ElemType>* p)
    {
        LinkNode<ElemType>* p1=head;
        while (p1->next != p)
            p1 = p1->next;
        return p1;
    }
    void delp(LinkNode<ElemType>* p)
    {
        if (p == head && p == tail)
        {
            //only have one
            //没写删除元素
            head = NULL;
            tail = NULL;
            delete p;
            return;
        }
        if (p == head)
        {
            LinkNode<ElemType>* p1 = head->next;
            head = p1;
            tail->next = head;
            return;
        }
        if (p == tail)
        {
            LinkNode<ElemType>* p1 = front(p);
            p1->next = head;
            tail = p1;
            return;
        }
        if (p != head && p != tail)
        {
            LinkNode<ElemType>* p1 = front(p);
            p1->next = p->next;
            return;
        }
        return;
    }
    void del(int n)
    {
        //删除链表指定元素
        LinkNode<ElemType>* p = getPlace(n);
        if (p == head && p == tail)
        {
            //only have one
            //没写删除元素
            head = NULL;
            tail = NULL;
            delete p;
            return;
        }
        if (p == head)
        {
            LinkNode<ElemType>* p1 = head->next;
            head = p1;
            tail->next = head;
            return;
        }
        if (p == tail)
        {
            LinkNode<ElemType>* p1 = getPlace(n - 1);
            p1->next = head;
            tail = p1;
            return;
        }
        if (p != head && p != tail)
        {
            LinkNode<ElemType>* p1 = getPlace(n - 1);
            p1->next = p->next;
            return;
        }
        return; 
    }
    void del_clear()
    {
        //释放链表

        return;
    }
    int size() const//ok
    {
        //返回链表的长度
        int cnt = 0;
        LinkNode<ElemType>* p;
        bool fir = 0;
        p = head;
        if (p == NULL)
        {
            return 0;
        }
        while (1)
        {
            if (p == head && fir == 1)
                break;
            //------------
            //循环操作
            cnt++;
            //------------
            fir = 1;
            p = p->next;
        }
        return cnt;
    }
    bool empty() const//ok
    {
        //判断链表是否为空表
        if (size() == 0 || head == NULL)
        {
            return 0;
        }
        return 1;
    }
    LinkNode<ElemType>* getHead() //ok
    { 
        //获取循环链表头结点
        return head; 
    }
    LinkNode<ElemType>* getTail() //ok
    { 
        //获取循环链表尾结点
        return tail; 
    }
    void changeTail(LinkNode<ElemType>*p)
    {
        tail = p;
        return;
    }
    void changeHead(LinkNode<ElemType>*p)
    {
        head = p;
        return;
    }
    LinkNode<ElemType>* getNextn(LinkNode<ElemType>* p, int n)
    {
        while (n--)
        {
            p = p->next;
        }
        return p;
    }
    LinkNode<ElemType>* getPlace(int n)
    {
        LinkNode<ElemType>* p;
        p = head;
        if (p == NULL)
        {
            cout << "wrong! NULL List!!!" << endl;
            return NULL;
        }
        while (n--)
        {
            p = p->next;
        }
        return p;
    }
    ElemType getNum(int n)
    {
        LinkNode<ElemType>* p = getPlace(n);
        return p->data;
    }
    bool Insert_next(int pos, ElemType num)
    {
        //在链表的第pos个位置之后插入num元素
        
    }
    bool InsFirst(ElemType num)//ok
    {
        //在首结点之前插入一个结点
        if (head == NULL)
        {
            //空链表插入
            head = new LinkNode<ElemType>;
            head->data = num;
            tail = head;
            tail->next = head;
            return 0;
        }
        LinkNode<ElemType>* p = new LinkNode<ElemType>;
        p->next = head;
        p->data = num;
        head = p;
        tail->next = head;
        return 1;
    }
    void push_back(ElemType num)//ok
    {
        if (head == NULL)
        {
            //空链表插入
            head = new LinkNode<ElemType>;
            head->data = num;
            tail = head;
            tail->next = head;
            return;
        }
        LinkNode<ElemType>* p = new LinkNode<ElemType>;
        p->data = num;
        p->next = head;
        tail->next = p;
        tail = p;
        return;
    }
    bool ListTraverse() const//ok
    {
        LinkNode<ElemType>* p;
        bool fir = 0;
        p = head;
        if (p == NULL)
        {
            cout << "wrong! NULL List!!!" << endl;
            return 0;
        }
        while (1)
        {
            if (p == head && fir == 1)
                break;
            //------------
            //循环操作
            cout << p->data;
            if (p->next != head)
                cout << "->";
            else
                cout << endl;
            //------------
            fir = 1;
            p = p->next;
        }
        return 1;
    }
};
//CirLinkList<int> a;
//===============================================================
struct node{
    int number;
    int code;
};
int main()
{
    int n;
    node num;
    int i, j;
    CirLinkList<node> a;
    cin >> n;
    for (i = 0; i < n; i++)
    {
        cin >> num.code;
        num.number = i + 1;
        a.push_back(num);
    }
    int t;
    cin >> t;
    queue<node>ans;
    LinkNode<node>* p,*p1;
    bool fir = 0;
    p1 = a.getHead();
    p = p1;
    while (1)
    {
        if (p == p1 && fir == 1)
            break;
        //------------
        //循环操作
        ans.push(p->data);
        //------------
        fir = 1;
        p = p->next;
    }
    while (!ans.empty())
    {
        num = ans.front();
        cout << "(" << num.number << "," << num.code << ")";
        if (ans.size() != 1)
            cout << "->";
        else
            cout << endl;
        ans.pop();
    }
    p = a.getHead();
    
    while (a.size() != 0)
    {
        p = a.getNextn(p,t-1);
        num = p->data;
        t = num.code;
        a.delp(p);
        p = p->next;
        
        ans.push(num);
    }
    cout << endl;
    while (!ans.empty())
    {
        num = ans.front();
        cout << num.number;
        if (ans.size() != 1)
            cout << "->";
        else
            cout << endl;
        ans.pop();
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值