create/reverse 链表的最佳方法是什么?
What is the best way to create/reverse a linked list?
我是编程初学者,我已经学会了如何反转链表。
下面是我用来制作一个带有随机值的链表并将其反转的代码。我想知道最好的方法是什么。感谢您的建议!祝你有美好的一天!
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
// node
typedef struct node{
int number;
struct node *next;
}node;
// functions
node *reversedList(node *head);
void printList(node *head);
node *create(int size);
int main(void)
{
srand(time(0));
// ........
}
node *reversedList(node *curr)
{
// a->b->c->d
// d->c->b->a
node *previous = NULL;
while(curr->next != NULL)
{
node *curr_temp = curr->next;
curr->next = previous;
previous = curr;
curr = curr_temp;
}
curr->next = previous;
return curr;
}
void printList(node *head)
{
if (head == NULL)
return;
printf("%d ",head->number);
printList(head->next);
}
node *create(int size)
{
if(size == 0)
return NULL;
node *n = malloc(sizeof(node));
n->number = rand() % 10;
n->next = create(size - 1);
return n;
}
反转 singly-linked 列表的最佳方法是在不调用未定义行为的情况下反转它
在您的函数 reversedList
中,您没有检查传递的指针 curr
是否等于 NULL
。所以while循环中的表达式
while(curr->next != NULL)
可以调用未定义的行为。
函数可以这样定义
node * reversedList( node *head )
{
// a->b->c->d
// d->c->b->a
node *curr = head;
head = NULL;
while ( curr != NULL )
{
Node *tmp = curr;
curr = curr->next;
tmp->next = head;
head = tmp;
}
return head;
}
注意递归函数printList
的参数要用限定符const
声明,因为列表在函数内部没有变化
void printList(cosnt node *head);
我将按以下方式声明和定义递归函数
FILE * printList( const node *head, FILE *fp )
{
if ( head )
{
fprintf( fp, "%d ", head->number );
printList( head->next, fp );
}
return fp;
}
主要你可以写
fputc( '\n', printList( head, stdout ) );
使用这样的函数,您可以在包括文件流在内的任何流中输出列表。
旁注: 奇怪的是,您为反转做了一个迭代解决方案,但为 create
做了一个 递归 解决方案,并且printList
您的函数非常接近最优。
但是,您 curr->next
两次 。不可否认,有了优化器,应该不会有额外的速度损失。
但是,我会简化它。而且,我认为 for
循环可以更简洁:
node *
reversedFor(node *curr)
{
// a->b->c->d
// d->c->b->a
node *prev = NULL;
node *next;
for (; curr != NULL; curr = next) {
next = curr->next;
curr->next = prev;
prev = curr;
}
return prev;
}
编辑: 而且,正如 Vlad 提到的,您在取消引用之前不检查 curr
是否为 non-null。因此,我的上述重构意外地修复了该错误。
以下是我要清理的所有内容:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// node
typedef struct node {
int number;
struct node *next;
} node;
// functions
node *reversedList(node *head);
node *reversedFor(node *head);
void printList(node *head,const char *tag);
node *create(int size);
node *delList(node *head);
typedef node *(revfnc_p)(node *head);
void
dotest(revfnc_p fnc,const char *tag)
{
node *list;
printf("dotest: %s\n",tag);
list = create(10);
printList(list,"orig");
list = fnc(list);
printList(list,"revd");
delList(list);
}
int
main(void)
{
dotest(reversedList,"reversedList");
dotest(reversedFor,"reversedFor");
return 0;
}
node *
reversedList(node *curr)
{
// a->b->c->d
// d->c->b->a
node *previous = NULL;
while (curr->next != NULL) {
node *curr_temp = curr->next;
curr->next = previous;
previous = curr;
curr = curr_temp;
}
curr->next = previous;
return curr;
}
node *
reversedFor(node *curr)
{
// a->b->c->d
// d->c->b->a
node *prev = NULL;
node *next;
for (; curr != NULL; curr = next) {
next = curr->next;
curr->next = prev;
prev = curr;
}
return prev;
}
void
printList(node *head,const char *tag)
{
if (tag != NULL)
printf("%s:",tag);
for (node *curr = head; curr != NULL; curr = curr->next)
printf(" %d",curr->number);
printf("\n");
}
node *
create(int size)
{
node *head = NULL;
node *prev = NULL;
node *curr;
for (int idx = 0; idx < size; ++idx) {
curr = malloc(sizeof(*curr));
curr->number = idx;
curr->next = NULL;
if (head == NULL)
head = curr;
else
prev->next = curr;
prev = curr;
}
return head;
}
node *
delList(node *curr)
{
node *next;
for (; curr != NULL; curr = next) {
next = curr->next;
free(curr);
}
return curr;
}
程序输出如下:
dotest: reversedList
orig: 0 1 2 3 4 5 6 7 8 9
revd: 9 8 7 6 5 4 3 2 1 0
dotest: reversedFor
orig: 0 1 2 3 4 5 6 7 8 9
revd: 9 8 7 6 5 4 3 2 1 0
我是编程初学者,我已经学会了如何反转链表。 下面是我用来制作一个带有随机值的链表并将其反转的代码。我想知道最好的方法是什么。感谢您的建议!祝你有美好的一天!
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
// node
typedef struct node{
int number;
struct node *next;
}node;
// functions
node *reversedList(node *head);
void printList(node *head);
node *create(int size);
int main(void)
{
srand(time(0));
// ........
}
node *reversedList(node *curr)
{
// a->b->c->d
// d->c->b->a
node *previous = NULL;
while(curr->next != NULL)
{
node *curr_temp = curr->next;
curr->next = previous;
previous = curr;
curr = curr_temp;
}
curr->next = previous;
return curr;
}
void printList(node *head)
{
if (head == NULL)
return;
printf("%d ",head->number);
printList(head->next);
}
node *create(int size)
{
if(size == 0)
return NULL;
node *n = malloc(sizeof(node));
n->number = rand() % 10;
n->next = create(size - 1);
return n;
}
反转 singly-linked 列表的最佳方法是在不调用未定义行为的情况下反转它
在您的函数 reversedList
中,您没有检查传递的指针 curr
是否等于 NULL
。所以while循环中的表达式
while(curr->next != NULL)
可以调用未定义的行为。
函数可以这样定义
node * reversedList( node *head )
{
// a->b->c->d
// d->c->b->a
node *curr = head;
head = NULL;
while ( curr != NULL )
{
Node *tmp = curr;
curr = curr->next;
tmp->next = head;
head = tmp;
}
return head;
}
注意递归函数printList
的参数要用限定符const
声明,因为列表在函数内部没有变化
void printList(cosnt node *head);
我将按以下方式声明和定义递归函数
FILE * printList( const node *head, FILE *fp )
{
if ( head )
{
fprintf( fp, "%d ", head->number );
printList( head->next, fp );
}
return fp;
}
主要你可以写
fputc( '\n', printList( head, stdout ) );
使用这样的函数,您可以在包括文件流在内的任何流中输出列表。
旁注: 奇怪的是,您为反转做了一个迭代解决方案,但为 create
做了一个 递归 解决方案,并且printList
您的函数非常接近最优。
但是,您 curr->next
两次 。不可否认,有了优化器,应该不会有额外的速度损失。
但是,我会简化它。而且,我认为 for
循环可以更简洁:
node *
reversedFor(node *curr)
{
// a->b->c->d
// d->c->b->a
node *prev = NULL;
node *next;
for (; curr != NULL; curr = next) {
next = curr->next;
curr->next = prev;
prev = curr;
}
return prev;
}
编辑: 而且,正如 Vlad 提到的,您在取消引用之前不检查 curr
是否为 non-null。因此,我的上述重构意外地修复了该错误。
以下是我要清理的所有内容:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// node
typedef struct node {
int number;
struct node *next;
} node;
// functions
node *reversedList(node *head);
node *reversedFor(node *head);
void printList(node *head,const char *tag);
node *create(int size);
node *delList(node *head);
typedef node *(revfnc_p)(node *head);
void
dotest(revfnc_p fnc,const char *tag)
{
node *list;
printf("dotest: %s\n",tag);
list = create(10);
printList(list,"orig");
list = fnc(list);
printList(list,"revd");
delList(list);
}
int
main(void)
{
dotest(reversedList,"reversedList");
dotest(reversedFor,"reversedFor");
return 0;
}
node *
reversedList(node *curr)
{
// a->b->c->d
// d->c->b->a
node *previous = NULL;
while (curr->next != NULL) {
node *curr_temp = curr->next;
curr->next = previous;
previous = curr;
curr = curr_temp;
}
curr->next = previous;
return curr;
}
node *
reversedFor(node *curr)
{
// a->b->c->d
// d->c->b->a
node *prev = NULL;
node *next;
for (; curr != NULL; curr = next) {
next = curr->next;
curr->next = prev;
prev = curr;
}
return prev;
}
void
printList(node *head,const char *tag)
{
if (tag != NULL)
printf("%s:",tag);
for (node *curr = head; curr != NULL; curr = curr->next)
printf(" %d",curr->number);
printf("\n");
}
node *
create(int size)
{
node *head = NULL;
node *prev = NULL;
node *curr;
for (int idx = 0; idx < size; ++idx) {
curr = malloc(sizeof(*curr));
curr->number = idx;
curr->next = NULL;
if (head == NULL)
head = curr;
else
prev->next = curr;
prev = curr;
}
return head;
}
node *
delList(node *curr)
{
node *next;
for (; curr != NULL; curr = next) {
next = curr->next;
free(curr);
}
return curr;
}
程序输出如下:
dotest: reversedList
orig: 0 1 2 3 4 5 6 7 8 9
revd: 9 8 7 6 5 4 3 2 1 0
dotest: reversedFor
orig: 0 1 2 3 4 5 6 7 8 9
revd: 9 8 7 6 5 4 3 2 1 0