循环链表应用------Josephus环问题


// 编号为1-N的N个人按顺时针方向围坐一圈,每个人持有一个密码(正整数,可以自由输入)开始选一个正整数作为报数上限值M,
// 从第一个人开始按顺时针方向自1开始顺序报数,报到M时停止报数。报到M的值的人出列,将它的值作为新的M值,从他顺时针方
// 向的下一个人开始从1报数,如此下去,直到所有人出列为止;

#include<iostream>
using namespace std;
// 循环链表结构体
typedef struct _Node
{
    int data;  // 数据域;
    struct _Node *next;   // 指针域;
}DNode,*DLinkList;

// 初始化函数
void InitDLinkList(DLinkList *pHead)
{
    *pHead = new DNode;
    (*pHead)->data = 0;
    (*pHead)->next = *pHead;
}

// 输出函数
void  ShowDLinkList(DLinkList pHead)
{
    DLinkList nPos = pHead;
    while (nPos->next!=pHead)
    {
        nPos = nPos->next;
        cout << nPos->data << "  ";
    }
    cout << endl;
}

// 循环链表长度(结点个数)
int GetDLinkListLength(DLinkList pHead)
{
    DLinkList nPos = pHead;
    int count = 0;
    while (nPos->next != pHead)
    {
        nPos = nPos->next;
        count++;
    }
    return count;
}

// 头插函数
void InsertHeadDLinkList(DLinkList *pHead,int value)
{
    DLinkList pNew = new DNode;
    pNew->data = value;
    // 如果头节点pHead后没有结点
    if ((*pHead)->next ==*pHead)
    {
        // 把新申请的结点,连接在头节点后;
        (*pHead)->next = pNew;
        pNew->next = *pHead;
    }
    // pHead后有节点的话
    else
    {
        // 把新申请的next,连接在头节点后的next链上;
        pNew->next = (*pHead)->next;
        // 把新申请的结点,连接在头节点后;
        (*pHead)->next = pNew;
    }
    // 销毁头节点的
}

// 尾插函数
void InsertTailDLinkList(DLinkList *pHead,int value)
{
    DLinkList pNew = new DNode;
    pNew->data = value;
    if ((*pHead)->next==*pHead)
    {  
        InsertHeadDLinkList(pHead,value);
    }
    else
    {
        DLinkList nPos = *pHead;
        while (nPos->next != *pHead)
        {
            nPos = nPos->next;
        }
        nPos->next = pNew;
        pNew->next = *pHead;
    }
}

// 头删函数
void DeleteHeadDlinkList(DLinkList* pHead)
{
    DLinkList nPos = *pHead;
    if (nPos->next==*pHead)
    {
        return;
    //    delete nPos;
    //    nPos= NULL;
    }
    else
    {
        DLinkList temp = nPos->next;
        nPos->next = temp->next;
        delete temp;
        temp = NULL;
    }
}

// 尾删函数
void DeleteTailDLinkList(DLinkList *pHead)
{
    if ((*pHead)->next==*pHead)
    {
        return;
    }
    else
    {
        DLinkList nPos = *pHead;
        while (nPos->next->next!=*pHead)
        {
            nPos = nPos->next;
        }
        DLinkList temp = nPos->next;    // 用临时变量记住倒数第二个数的结点
        nPos->next = *pHead;
        delete temp;
        temp= NULL;
    }
}

// 按下标插入结点
void InsertByIndex(DLinkList *pHead,int pos,int value)
{
    //  下标位置不能小于1,否则无法插入;
    if (pos<0)
    {
        return;
    }
     if(1==pos)     // 下标位置为1的时候进行头插;
    {  
        InsertHeadDLinkList(pHead,value);
        return;
    }
    if(pos>=GetDLinkListLength(*pHead))  // 当插入位置超过循环链表的长度时,进行尾插;
    {
        InsertTailDLinkList(pHead,value);
        return;
    }
    else
    {
        DLinkList nPos = *pHead;
        DLinkList pNew = new DNode;
        pNew->data = value;
        for (int i = 0; i < pos - 1; i++)
            nPos = nPos->next;
        DLinkList temp = nPos;   // 临时变量记住nPos的位置
        pNew->next = temp->next;
        nPos->next = pNew;
    }
}

// 按值下标删除函数
void DeletByIndex(DLinkList *pHead, int pos)
{
    DLinkList nPos = *pHead;
    if (1 == pos)
    {
        DeleteHeadDlinkList(pHead);
        return;
    }
    if (pos >= GetDLinkListLength(*pHead))
    {
        DeleteTailDLinkList(pHead);
        return;
    }
    for (int i = 0; i < pos - 1; i++)
        nPos = nPos->next;
    DLinkList temp = nPos->next;
    nPos->next = temp->next;
    delete temp;
    temp = NULL;
}

// 按值删除函数
void DleteByValue(DLinkList *pHead,int value)
{
    DLinkList nPos = *pHead;
    for (int i = 0; i < GetDLinkListLength(*pHead) && nPos->next->data != value; i++)
    {
        nPos = nPos->next;
    }
    DLinkList temp = nPos->next;
    nPos->next = temp->next;
    delete temp;
    temp = NULL;
}

// 销毁头节点函数
void DestoryHeadDNode(DLinkList *pHead)
{
    delete *pHead;
    *pHead = NULL;
}

// 销毁节点函数
void DestoryDLinkList(DLinkList* pHead)
{
    DLinkList nPos = *pHead;
    while (nPos->next!=*pHead)
    {
        DeleteHeadDlinkList(pHead);
    }
    if ((*pHead)->next=*pHead)
    {
        DestoryHeadDNode(pHead);
    }
}

// 每次找出要出列的那个人,并删除结点,返回它的密码密码,作为下次循环的终点;
int FinPopDNode(DLinkList *pHead,int passWord)
{
    int i;
    int pt = 0;
    DLinkList nPos = *pHead;
    int secrectValue = 1;

    while (secrectValue!=passWord)
    {
        if (nPos->next==*pHead)
        {
            nPos = nPos->next;
        }
        else
        {
            nPos = nPos->next;
            secrectValue++;
        
        }
    }
    if (nPos->next == *pHead)
    {
        nPos = nPos->next;
    }
    DLinkList temp = nPos->next;
    nPos->next = temp->next;
    cout << temp->data << "  ";
    pt = temp->data;
    delete temp;
    temp = NULL;

    return pt;
}

// 删除所有结点并打印出出列顺序
void PopDNode(DLinkList *pHead,int passWord)
{
    DLinkList nPos = *pHead;
    int i = 0;
    int DelDnNode = 0; // 用来存放出列的那个人的密码;
//    int pt = 0;
    int secrectValue = 1;
    if (0 == passWord)
        return;
 // 第一次应随机输入一个要出列的密码,开始出列;
    for (int j = 0; j<=GetDLinkListLength(*pHead); j++)
    {
        if (0 == j)
        {
            while (secrectValue != passWord)
            {
                if (nPos->next == *pHead)
                {
                    nPos = nPos->next;
                }
                else
                {
                    nPos = nPos->next;
                    secrectValue++;
                }
            }
            if (nPos->next == *pHead)
            {
                nPos = nPos->next;
            }
            DLinkList temp = nPos->next;
            nPos->next = temp->next;
            if (GetDLinkListLength(*pHead) == 0)
            {
                break;
            }
            cout << temp->data << "  ";
            DelDnNode = temp->data;
            delete temp;
            temp = NULL;
        }

        for (int i = 0; i != DelDnNode /*&& GetDLinkListLength(*pHead) >= 1*/; i++)
        {
            secrectValue = 0; // 需要重新赋值,否则会保留上次值;
            if (secrectValue<DelDnNode)   // 如果密码不为0继续循环
            {
                //    DelDnNode=FinPopDNode(&nPos, DelDnNode);
                while (secrectValue != DelDnNode-1)
                {
                    if (nPos->next == *pHead)
                    {
                        nPos = nPos->next;
                    }
                    else
                    {
                        nPos = nPos->next;
                        secrectValue++;

                    }
                }
                if (nPos->next == *pHead)
                {
                    nPos = nPos->next;

                }
                DLinkList temp = nPos->next;
                nPos->next = temp->next;
                cout << temp->data << "  ";
                DelDnNode = temp->data;
                delete temp;
                temp = NULL;
                break;
            }
        }
        j = 0;
    }
}

void Test(DLinkList *pHead)
{
    int i;
    int count = 0,passWord=0;
    InitDLinkList(pHead);
    cout << "请输入人数:" << endl;
    cin >> count;

    for (i = 0; i < count; i++)
    {
        int pass = 0;
        cout << "请给第"<<i+1<<"个人输入密码:" << endl;
        cin >> pass;
        InsertTailDLinkList(pHead,pass);
    }

    ShowDLinkList(*pHead);
    cout << "请输入第一个要出列的人的密码:" << endl;
    cin >> passWord;
    PopDNode(pHead,passWord);
    cout << endl;
}
int main(void)
{
    DLinkList pHead = NULL;
    Test(&pHead);
    
/*------------------Test----------------------
    InsertHeadDLinkList(&pHead,1);
    InsertHeadDLinkList(&pHead, 2);
    InsertHeadDLinkList(&pHead, 3);
    ShowDLinkList(&pHead);
//    DeleteHeadDlinkList(&pHead);
    ShowDLinkList(&pHead);
//    DeleteHeadDlinkList(&pHead);
    ShowDLinkList(&pHead);
//    DeleteHeadDlinkList(&pHead);
//    DeleteHeadDlinkList(&pHead);
//    DestoryHeadDNode(&pHead);
-----------------Test------------------------
*/
    //InsertTailDLinkList(&pHead,1);
    //InsertTailDLinkList(&pHead, 2);
    //InsertTailDLinkList(&pHead, 3);
    //InsertTailDLinkList(&pHead, 4);
    //InsertTailDLinkList(&pHead, 5);
    //InsertTailDLinkList(&pHead, 6);
    //InsertTailDLinkList(&pHead, 7);
    //InsertByIndex(&pHead,1,8);
    //InsertByIndex(&pHead,9, 9);
    //InsertByIndex(&pHead, 9, 20);
    //InsertByIndex(&pHead, 6, 30);
    //ShowDLinkList(pHead);


    //DeletByIndex(&pHead,6);
    //ShowDLinkList(pHead);
    //int a = GetDLinkListLength(pHead);
    //cout << a << endl;
//    DleteByValue(&pHead,20);
//    ShowDLinkList(pHead);
    DestoryDLinkList(&pHead);


    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值