C++创建单循环链表写约瑟夫环问题报错内存访问权限冲突

创建循环单链表写约瑟夫环问题,一直报错0xDDDDDDDD
源代码
#include
using namespace std;
struct Node//结点类型
{
int data; //数据域
Node* next; //指针域
};
int main()
{
int num, k;//n为人数,k为报数到几出列
cout << "请输入参加游戏的人数:";
cin >> num;
cout << "每报数到几出列:";
cin >> k;
struct Node* H = NULL, * r = NULL;//H是头指针,r是尾指针,都先赋初值为空
struct Node* p, * q;//用两个指针方便后面删除操作,使q一直是p的前驱
//创建一个无头结点的循环单链表,从尾部插入n个节点
for (int i = 1; i <= num; i++)
{
p = (struct Node*)malloc(sizeof(struct Node));
p->data = i;
if (H == NULL)//对于第一个节点的操作
H = r = p;//使头尾指针都指向第一个节点,同时也固定了头指针
else//对于其他节点的操作
{
p->next = H;//新增节点指向头指针,实现循环
r->next = p;
r = p;//新表尾替换旧表尾
}
}
p = H; q = r;//p指向第一个节点,q指向表尾,q一直做p前驱
int count = 0;//记录出列人数
while (count != num)//count=num代表所有人都出列
{
for (int j = 1; j <= k;)
{
if (j != k)
{
q = q->next;
p = p->next;
j++;
}
if (j == k)//报数到k删除节点
{
count++;
q->next = p->next;
cout << "第" << count << "个出列的人是:" << p->data << endl;
free(p);//删除p
p = q->next;//让p重新指向q的后继
j = 1;
}
}
}
return 0;
}

img

报错:

img

主要原因是你最后循环中,while其实没起到作用,都在for循环中进行了。可for循环却没有有效的结束条件,因为一旦i==k,你就会删除节点,然后把j设置为1。其实这个for是个死循环。当节点都删除后,你的 p和q还在移动,自然就死掉了。
修改也很简单,在for循环的if(j==k)的末尾增加while的条件判断
if(count == num)
break;
即可。
最后代码如下:

#include <iostream>
using namespace std;
struct Node//结点类型
{
    int data; //数据域
    Node* next; //指针域
};
int main()
{
    int num, k;//n为人数,k为报数到几出列
    cout << "请输入参加游戏的人数:";
    cin >> num;
    cout << "每报数到几出列:";
    cin >> k;
    struct Node* H = NULL, * r = NULL;//H是头指针,r是尾指针,都先赋初值为空
    struct Node* p, * q;//用两个指针方便后面删除操作,使q一直是p的前驱
    //创建一个无头结点的循环单链表,从尾部插入n个节点
    for (int i = 1; i <= num; i++)
    {
        p = (struct Node*)malloc(sizeof(struct Node));
        p->data = i;
        if (H == NULL)//对于第一个节点的操作
            H = r = p;//使头尾指针都指向第一个节点,同时也固定了头指针
        else//对于其他节点的操作
        {
            p->next = H;//新增节点指向头指针,实现循环
            r->next = p;
            r = p;//新表尾替换旧表尾
        }
    }
    p = H; q = r;//p指向第一个节点,q指向表尾,q一直做p前驱
    int count = 0;//记录出列人数
    for (int j = 1; j <= k;)
    {
        if (j != k)
        {
            q = q->next;
            p = p->next;
            j++;
        }
        if (j == k)//报数到k删除节点
        {
            count++;
            q->next = p->next;
            cout << "第" << count << "个出列的人是:" << p->data << endl;
            free(p);//删除p
            if(count == num)
                break;
            p = q->next;//让p重新指向q的后继
            j = 1;
        }
    }
    return 0;
}