编程之美 3.4 的扩展问题:遍历一遍单链表,使得元素顺序相反

来源:互联网 发布:java开发设计师 编辑:程序博客网 时间:2024/05/22 03:05

题干

编写一个函数,给定一个链表的头指针,要求只遍历一次,将单链表中的元素顺序反转过来。

解题思路

我想按着顺序把一个指针的下一个元素改为它之前的元素,最后返回表尾元素,所以在一次遍历过程中需要额外三个指针

  1. 指向当前元素的前一个元素
  2. 指向当前元素
  3. 指向当前元素的下一个元素

这是因为在改变一个指针的指向时,会失去其下一个元素,所以必须要先保存指向当前元素的下一个元素。因为要改为指向前一个元素,所以需要指向当前元素的前一个元素。

注意对表头元素和表尾元素要特殊处理。

代码

#include <stdio.h>#include <string.h>#include <stdlib.h>#define NULL ((void *)0)struct node{struct node *next;char *str;};struct node *reverse(struct node *a){struct node *pre,*now,*next;/* 对于单链表头我们特殊处理 */pre=NULL;now=a;next=a->next;now->next=pre;/*对于不是表头还不是尾部,都循环处理*/while(1){pre=now;now=next;if(now->next==NULL) break;//如果到表尾了,break掉,特殊处理next=now->next;now->next=pre;}now->next=pre;//到表尾了,now的next就是空,所以不用特殊记录了return now;}int main(int argc, char **argv) {struct node *a;a=malloc(sizeof(struct node));struct node *b;b=malloc(sizeof(struct node));struct node *c;c=malloc(sizeof(struct node));struct node *d;d=malloc(sizeof(struct node));a->str="aaa";a->next=b;b->str="bbb";b->next=c;c->str="ccc";c->next=d;d->str="ddd";d->next=NULL;struct node *temp;temp=malloc(sizeof(struct node));temp=a;while(temp){printf("%s->",temp->str);temp=temp->next;}printf("NULL \n");free(temp);struct node *revptr;revptr=malloc(sizeof(struct node));revptr=reverse(a);while(revptr){printf("%s->",revptr->str);revptr=revptr->next;}printf("NULL \n");free(revptr);}
运行结果:

asd@asd-desktop:~/workspace/test/src$ ./a.out aaa->bbb->ccc->ddd->NULL ddd->ccc->bbb->aaa->NULL asd@asd-desktop:~/workspace/test/src$ 

递归的解法

在这篇博客: 总结:来自"v_JULY_v"的微软面试100题(2010年)里面的有一道题,就已经有这个题的递归解法了,下面贴一下代码:
/**  * 递归的做法  */  Node * reverse(Node * head) {    if (head == NULL) return head;    if (head->next == NULL) return head;    Node * ph = reverse(head->next);//*ph指针会一直保留尾节点,也就是颠倒后的头节点    head->next->next = head;    head->next = NULL;    return ph;  }  
为了更好的理解,我特意画出了图形,在这有两个节点的情况是如此,必须注意只递归调用了一次,我每次在这个问题上都要纠结挺久的,所以刻意画个图:



0 0
原创粉丝点击