// 编号为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;
}