将单链表翻转的两种方法
Posted veli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将单链表翻转的两种方法相关的知识,希望对你有一定的参考价值。
单链表翻转很容易理解,例如:
输入: NODE1->NODE2->NODE3->NODE4->NODE5->NULL
输出: NODE5->NODE4->NODE3->NODE2->NODE1->NULL
那么,定义单链表如下: (为简单起见,将data字段定义为int, 当然实际应用中data很可能是一个复杂的结构体)
typedef struct list_s { int data; struct list_s *next; } list_t;
如何将单链表翻转,有如下两种方法。
- 使用N个辅助存储空间aux[],N为单链表中所有结点的个数。将所有结点的地址反向存入aux[]中,然后根据aux[]重新生成一个单链表。
- 只使用2个辅助存储空间,从头到尾遍历单链表并翻转。
其中,方法1使用了较多的辅助存储空间,但实现起来很简单,借助了栈(stack)的思想。 跟方法1比起来,方法2的时间效率和空间效率都要更胜一筹,不过实现起来难度稍大一点。
方法1的代码实现如下:
o foo1.c
1 static int get_length(list_t *head) 2 { 3 int len = 0; 4 for (list_t *p = head; p != NULL; p = p->next) 5 len++; 6 return len; 7 } 8 9 void reverse_singly_linked_list(list_t **head) 10 { 11 if (*head == NULL) 12 return; 13 14 int len = get_length(*head); 15 if (len < 2) 16 return; 17 18 list_t **aux = (list_t **)malloc(sizeof (list_t *) * len); 19 if (aux == NULL) /* error */ 20 return; 21 22 /* save addr of per node to aux[] */ 23 int index = 0; 24 for (list_t *p = *head; p != NULL; p = p->next) { 25 aux[len-1-index] = p; 26 index++; 27 } 28 29 /* rebuild the singly linked list by walking aux[] */ 30 *head = aux[0]; 31 for (int i = 0; i < len-1; i++) 32 aux[i]->next = aux[i+1]; 33 aux[len-1]->next = NULL; 34 35 free(aux); 36 }
方法2的代码实现如下:
o foo2.c
1 void reverse_singly_linked_list(list_t **head) 2 { 3 list_t *newhead = NULL; 4 list_t *this = *head; 5 list_t *prev = NULL; 6 7 while (this != NULL) { 8 /* 9 * If this->next is NULL, this is the tail node, which should 10 * be the new head 11 */ 12 if (this->next == NULL) 13 newhead = this; 14 15 /* 16 * ListIn: prevNode -> thisNode -> nextNode 17 * ListOut: prevNode <- thisNode <- nextNode 18 * 1. thisNode->next = prevNode; 19 * 2. prevNode = thisNode; 20 * 3. thisNode = thisNode->next; 21 */ 22 list_t *next = this->next; /* a. save the next */ 23 this->next = prev; /* b. reverse */ 24 prev = this; /* c. move prev forward */ 25 this = next; /* d. move this forward */ 26 } 27 28 *head = newhead; 29 }
用meld diff foo1.c foo2.c截图如下:
完整的C代码点这里
最后,对单链表翻转函数做单元测试需要考虑三种情况:
- 输入的单链表头结点指针为NULL
- 输入的单链表只有一个结点
- 输入的单链表包含多个结点
以上是关于将单链表翻转的两种方法的主要内容,如果未能解决你的问题,请参考以下文章