很不幸的告诉你,你的问题是访问了没有申请到的内存。你的函数虽然在函数体里面有给L,head,count申请内存空间,而且给他们赋值了,看起来好像是它们被初始化过,是不会出现访问内存违规的问题。那你就错了。你的函数根本没有返回值,没有用引用调用或者指针作为参数传值,在函数里面申请到的内存空间是在堆栈上,函数调用结束后,自动回收这部分空间,所以你的第一个函数调用结束后,你的变量就没有空间了。你后面的操作是枉然的,它们原来的首地址是在堆栈上,但是那部分空间已经被释放了!所以,会出现你说的那个问题。
如果你的算法没有问题的话,建议在初始化链表时用引用调用返回头结点的地址,然后在main()里面利用这个地址,就不会有问题了。指针是双刃剑,用得好,确实很强大 ,但是对指针的操作却不是一件简单的事,经验是不断在错误中总结出来的。给你一份我以前学数据结构的吧,约瑟夫问题是学链表必不可少的一个话题。仅供参考:
#include
#include
#include
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}Lode, *LinkList;
LinkList CreateCirList(void)
{//建立带头结点的循环链表,头结点只保存结点个数,不包括头结点本身,头结点也不参与运算。
static int LNodeNum = 0;
LinkList p1, p2, head;
p1 = (LNode*)malloc(sizeof(LNode));
head = p1;
p1->data = 0;
while(p1->data != -10){//假设以-10作为结点输入结束的标志
p2 = p1;
p1 = (LNode*)malloc(sizeof(LNode));
p2->next = p1;
printf("输入第%d个结点:", ++LNodeNum);
scanf("%d",&p1->data);
}
free(p1);
head->data = --LNodeNum;
p2->next = head->next;
printf("\n循环链表建立完毕,共有%d个结点!\n",head->data);
return head;
}//CreateCirList
void Joseph(LinkList &L, int num)
{//约瑟夫问题,每隔num个删除一个结点,剩下最后一个结点。如果链表带头结点,则剩两个结点。
LinkList p1 = L->next;
LinkList p2;
int i = 1;
printf("删除...\n");
for(; i < num, p1->next != p1; ++i, p1 = p1->next){
if (i == num - 1){//i是该删除结点的前一个结点
p2 = p1->next;//p2是该删除的结点
Sleep(100);
printf("%-4d",p2->data);
p1->next = p2->next;//p1的下一个结点是删除结点的下一个结点
free(p2);
p2 = NULL;
p1 = p1->next;//删除一个结点后,p1移到删除结点的下一个结点
i = 1;//重新计数
--L->data;//结点数减1
}
}
L->next = p1;//把头结点和最后剩下的结点链接起来
printf("\n");
}//Joseph
void PrintCirList(LinkList L)
{//输出循环链表
LinkList p = L;
printf("%-4d",p->data);//首先输出头结点,如果这两句在do{}中,则输出一次后,p = L->next,会停止输出
p = p->next;
do{
printf("%-4d",p->data);
p = p->next;
}while(p != L->next);//当输出完最后一个结点时,最后一个结点的下一个结点是链表的第二个结点
printf("\n");
}//PrintCirList
int main()
{
LinkList head;
head = CreateCirList();
PrintCirList(head);
Joseph(head, 4); // 当然可以是其他值
PrintCirList(head);
return 0;
}