为什么不是我的 reverse();函数工作?
Why isn't my reverse(); function working?
我正在用 C 语言编写一个程序,用于反转单 linked 循环列表。由于某种原因,我不断收到分段错误。我确定问题出在 reverse
函数上,因为我尝试评论函数调用,程序运行正常。
对于我的 reverse()
函数,我使用了 3 个指针:prev
、next
和 curr
。逻辑是我将 运行 循环直到 curr
获取 head
的地址,它将存储在最后一个节点的 link
部分,因为它是一个循环 linked 列表。我将使用 prev
指针不断更新 curr->link
,这会将其 link 从下一个节点更改为上一个节点。
当循环中断时,head->link = prev;
和 head = prev;
将更新各自的地址,使它们指向反向列表的第一个节点。
//reversing CLL
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
} *head;
void reverse() {
struct node *prev = NULL, *curr = head, *next;
while (curr != head) {
next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
}
head->link = prev;
head = prev;
}
void createList(int n) {
int i, data;
head = (struct node *)malloc(sizeof(struct node));
struct node *ptr = head, *temp;
printf("Enter data of node 1\t");
scanf("%d", &data);
head->data = data;
head->link = NULL;
for (i = 2; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
printf("Enter data of node %d\t", i);
scanf("%d", &data);
temp->data = data;
temp->link = NULL;
ptr->link = temp;
ptr = ptr->link;
}
ptr->link = head;
}
void disp() {
struct node *ptr = head;
do {
printf("%d\t", ptr->data); //gdb debugger shows problem is in this line
ptr = ptr->link;
} while (ptr != head);
}
int main() {
int n;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
createList(n);
printf("\n\nList is displayed below!\n");
disp();
printf("\n\nReversing list ...\n");
reverse(); // on commenting this call, disp() function
// works accurately showing node data non-reversed
disp();
printf("\n\nList successfully reversed!\n");
}
reverse()
函数中的循环立即退出,因为 curr
被初始化为 head
的值,因此测试 while (curr != head)
在第一次迭代时为假。
reverse()
然后将head->link
设置为NULL
最后head
也设置为NULL
(prev
的初始值) ,这解释了后续 disp()
函数中的分段错误,其中您使用了无法处理空列表的 do { } while (pre != head)
。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
};
struct node *reverse(struct node *head) {
struct node *prev = NULL, *curr = head;
if (head) {
do {
struct node *next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
} while (curr != head);
curr->link = prev;
head = prev;
}
return head;
}
struct node *createList(int n) {
struct node *head = NULL, *tail = NULL, *temp;
int i;
for (i = 1; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
temp->data = 0;
temp->link = NULL;
printf("Enter data of node %d\t", i);
scanf("%d", &temp->data);
if (head == NULL) {
head = temp;
} else {
tail->link = temp;
}
tail = temp;
temp->link = head;
}
return head;
}
void disp(struct node *head) {
if (head) {
struct node *ptr = head;
do {
printf("%d\t", ptr->data);
ptr = ptr->link;
} while (ptr != head);
}
}
int main() {
struct node *head;
int n = 0;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
head = createList(n);
printf("\n\nList is displayed below!\n");
disp(head);
printf("\n\nReversing list ...\n");
head = reverse(head);
disp(head);
printf("\n\nList successfully reversed!\n");
// should free the list
return 0;
}
对于初学者来说,使用全局变量是个坏主意head
struct node {
int data;
struct node *link;
} *head;
在这种情况下,函数依赖于全局变量,您不能在一个程序中使用多个列表。
由于这次初始化
struct node *prev = NULL, *curr = head, *next;
^^^^^^^^^^^^
while 循环的条件
while (curr != head) {
永远不会计算为真,因为最初指针 curr
等于指针 head
.
此外,如果列表为空,则此语句
head->link = prev;
调用未定义的行为。
这是一个演示程序,展示了如何在 main 中声明列表,然后将其反转。
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *link;
};
size_t assign( struct node **head, const int a[], size_t n )
{
while ( *head )
{
struct node *tmp = *head;
*head = ( *head )->link;
free( tmp );
}
size_t total = 0;
struct node *first = NULL;
while ( total < n && ( *head = malloc( sizeof( struct node ) ) ) != NULL )
{
( *head )->data = a[total];
( *head )->link = NULL;
++total;
if ( first == NULL ) first = *head;
head = &( *head )->link;
}
if ( first != NULL ) *head = first;
return total;
}
void display( const struct node *head )
{
if ( head != NULL )
{
const struct node *current = head;
do
{
printf( "%d -> ", current->data );
} while ( ( current = current->link ) != head );
}
puts( "null" );
}
struct node * reverse( struct node **head )
{
if ( *head )
{
struct node *last = *head;
struct node *prev = NULL;
while ( ( *head )->link != last )
{
struct node *current = *head;
*head = ( *head )->link;
current->link = prev;
prev = current;
}
( *head )->link = prev;
last->link = *head;
}
return *head;
}
int main(void)
{
struct node *head = NULL;
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
assign( &head, a, sizeof( a ) / sizeof( *a ) );
display( head );
display( reverse( &head ) );
display( reverse( &head ) );
return 0;
}
程序输出为
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
我正在用 C 语言编写一个程序,用于反转单 linked 循环列表。由于某种原因,我不断收到分段错误。我确定问题出在 reverse
函数上,因为我尝试评论函数调用,程序运行正常。
对于我的 reverse()
函数,我使用了 3 个指针:prev
、next
和 curr
。逻辑是我将 运行 循环直到 curr
获取 head
的地址,它将存储在最后一个节点的 link
部分,因为它是一个循环 linked 列表。我将使用 prev
指针不断更新 curr->link
,这会将其 link 从下一个节点更改为上一个节点。
当循环中断时,head->link = prev;
和 head = prev;
将更新各自的地址,使它们指向反向列表的第一个节点。
//reversing CLL
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
} *head;
void reverse() {
struct node *prev = NULL, *curr = head, *next;
while (curr != head) {
next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
}
head->link = prev;
head = prev;
}
void createList(int n) {
int i, data;
head = (struct node *)malloc(sizeof(struct node));
struct node *ptr = head, *temp;
printf("Enter data of node 1\t");
scanf("%d", &data);
head->data = data;
head->link = NULL;
for (i = 2; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
printf("Enter data of node %d\t", i);
scanf("%d", &data);
temp->data = data;
temp->link = NULL;
ptr->link = temp;
ptr = ptr->link;
}
ptr->link = head;
}
void disp() {
struct node *ptr = head;
do {
printf("%d\t", ptr->data); //gdb debugger shows problem is in this line
ptr = ptr->link;
} while (ptr != head);
}
int main() {
int n;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
createList(n);
printf("\n\nList is displayed below!\n");
disp();
printf("\n\nReversing list ...\n");
reverse(); // on commenting this call, disp() function
// works accurately showing node data non-reversed
disp();
printf("\n\nList successfully reversed!\n");
}
reverse()
函数中的循环立即退出,因为 curr
被初始化为 head
的值,因此测试 while (curr != head)
在第一次迭代时为假。
reverse()
然后将head->link
设置为NULL
最后head
也设置为NULL
(prev
的初始值) ,这解释了后续 disp()
函数中的分段错误,其中您使用了无法处理空列表的 do { } while (pre != head)
。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
};
struct node *reverse(struct node *head) {
struct node *prev = NULL, *curr = head;
if (head) {
do {
struct node *next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
} while (curr != head);
curr->link = prev;
head = prev;
}
return head;
}
struct node *createList(int n) {
struct node *head = NULL, *tail = NULL, *temp;
int i;
for (i = 1; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
temp->data = 0;
temp->link = NULL;
printf("Enter data of node %d\t", i);
scanf("%d", &temp->data);
if (head == NULL) {
head = temp;
} else {
tail->link = temp;
}
tail = temp;
temp->link = head;
}
return head;
}
void disp(struct node *head) {
if (head) {
struct node *ptr = head;
do {
printf("%d\t", ptr->data);
ptr = ptr->link;
} while (ptr != head);
}
}
int main() {
struct node *head;
int n = 0;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
head = createList(n);
printf("\n\nList is displayed below!\n");
disp(head);
printf("\n\nReversing list ...\n");
head = reverse(head);
disp(head);
printf("\n\nList successfully reversed!\n");
// should free the list
return 0;
}
对于初学者来说,使用全局变量是个坏主意head
struct node {
int data;
struct node *link;
} *head;
在这种情况下,函数依赖于全局变量,您不能在一个程序中使用多个列表。
由于这次初始化
struct node *prev = NULL, *curr = head, *next;
^^^^^^^^^^^^
while 循环的条件
while (curr != head) {
永远不会计算为真,因为最初指针 curr
等于指针 head
.
此外,如果列表为空,则此语句
head->link = prev;
调用未定义的行为。
这是一个演示程序,展示了如何在 main 中声明列表,然后将其反转。
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *link;
};
size_t assign( struct node **head, const int a[], size_t n )
{
while ( *head )
{
struct node *tmp = *head;
*head = ( *head )->link;
free( tmp );
}
size_t total = 0;
struct node *first = NULL;
while ( total < n && ( *head = malloc( sizeof( struct node ) ) ) != NULL )
{
( *head )->data = a[total];
( *head )->link = NULL;
++total;
if ( first == NULL ) first = *head;
head = &( *head )->link;
}
if ( first != NULL ) *head = first;
return total;
}
void display( const struct node *head )
{
if ( head != NULL )
{
const struct node *current = head;
do
{
printf( "%d -> ", current->data );
} while ( ( current = current->link ) != head );
}
puts( "null" );
}
struct node * reverse( struct node **head )
{
if ( *head )
{
struct node *last = *head;
struct node *prev = NULL;
while ( ( *head )->link != last )
{
struct node *current = *head;
*head = ( *head )->link;
current->link = prev;
prev = current;
}
( *head )->link = prev;
last->link = *head;
}
return *head;
}
int main(void)
{
struct node *head = NULL;
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
assign( &head, a, sizeof( a ) / sizeof( *a ) );
display( head );
display( reverse( &head ) );
display( reverse( &head ) );
return 0;
}
程序输出为
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null