A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 程潇 中级黑马   /  2012-7-21 20:46  /  5181 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

实现一个链表的反转算法。
这是以前面试的时候碰到过的一个题目

6 个回复

正序浏览
张凯 中级黑马 2012-7-22 09:25:30
7#
先说下单向链表的反转:
声明函数原型为:
void reverseLinkedList(item * header);

    这里,item为链表的元素类型,并假定其中包含了一个指向下一个元素的指针字段:
item * next;
和一些数据字段。

    函数参数header是一个指向item类型数据的指针,顾名思义,这个item类型的数据就是要反转的单向链表的头元素(注意,这里假定了这个单向链表是有头元素,而且头元素的数据类型与链表元素的类型是一致的)。

    下面再做一些假设:

    程序声明了一个全局变量或者预编译的常量即:
const int NULL = 0;
或者,
#define NULL 0

    因此可以用NULL来表示一个空指针。

    于是我们规定,header指向的链表的最后一个元素的next值为NULL。

    现在我们来实现函数:
  1. void reverseLinkedList(item * header){

  2.     item * newNext = NULL, curItem = header->next, oldNext = header->next->next;

  3.     while (oldNext != NULL){

  4.         curItem->next = newNext;

  5.         newNext = curItem;

  6.         curItem = oldNext;

  7.         oldNext = oldNext->next;

  8.     }

  9.     header.next = curItem;

  10. }

复制代码
以上算法中,通过三个指针curItem, newNext, oldNext分别指向当前操作的元素、当前操作的元素在新链表中的next(也就是curItem在原链表中的前一个元素)和当前操作元素的在原链表中的next,这样既保证了将当前操作的元素的next指向了它的前一元素,又保证了当前操作元素在原链表中的next所指向的元素地址不会丢失。

    算法中还要注意这三个指针初始值的设置、主循环方式和循环停止条件的选择,让函数体最精简,避免无谓的条件测试。另外记得在退出函数之前更新header->next指针的内容,使其指向更新后链表的首元素。

    当然,如果你把函数原型声明为:
void reverseLinkedList(item * first);

    即参数为链表的第一个元素,则相应把函数实现为以下即可:
  1. void reverseLinkedList(item * first){

  2.     item * newNext = NULL, curItem = first, oldNext = first->next;

  3.     while (oldNext != NULL){

  4.         curItem->next = newNext;

  5.         newNext = curItem;

  6.         curItem = oldNext;

  7.         oldNext = oldNext->next;

  8.     }

  9.     first = curItem;

  10. }

复制代码
对于双向链表的反转,问题就变得简单了,实际上就是交换item中next和previous指针的内容,如果有头元素,更新头元素next指针,指向原链表的最后一个元素。这里就不写出实现过程了。希望可以帮到你。

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 不错

查看全部评分

回复 使用道具 举报
这么个理解不知道对不对:
1.准备工作:使用LinkList创建一个集合(他底层不是由链表实现的吗?正好可以用),往里面添加一对元素
2.使用Collections类中的静态方法reverse()进行反转操作
这样实现对吗?如有不同意见欢迎交流
回复 使用道具 举报
温少邦 发表于 2012-7-21 21:47
最简单的链表了...只有add和delete方法
反转的做法是从第2个Node开始
把每个Node挪到链表的头,也就是root的 ...

谢谢支持,运行了一下,没有错误,可以支持反转
回复 使用道具 举报
最简单的链表了...只有add和delete方法
反转的做法是从第2个Node开始
把每个Node挪到链表的头,也就是root的位置

  1. public class LinkedList {
  2.         protected Node root=null;
  3.         public void add(int value){
  4.                 Node n=new Node(value);
  5.                 if(root!=null){
  6.                         Node last=root;
  7.                         while(last.next!=null)
  8.                                 last=last.next;
  9.                         last.next=n;
  10.                 }else{
  11.                         root=n;
  12.                 }
  13.         }
  14.         public void delete(int p){
  15.                 if(root==null){
  16.                         System.out.println("链表为空");
  17.                         return;
  18.                 }
  19.                 Node n=root;
  20.                 Node front=null;
  21.                 if(p==0){
  22.                         root=n.next;
  23.                 }
  24.                 while(p>0){
  25.                         front=n;
  26.                         n=n.next;
  27.                         p--;
  28.                         if(n==null){
  29.                                 System.out.println("越界");
  30.                                 return;
  31.                         }
  32.                 }
  33.                 front.next=n.next;
  34.         }
  35.         public void show(){
  36.                 if(root!=null){
  37.                         Node n=root;
  38.                         do{
  39.                                 System.out.println(n.value);
  40.                                 n=n.next;
  41.                         }while(n!=null);
  42.                 }
  43.         }
  44.         //从root的next那个Node开始,挪到链表的最前面,就是root上面去
  45.         public void reverse(){
  46.                 if(root.next!=null){                        //起码2个元素才反转
  47.                         Node n=root.next;                        //当前Node
  48.                         Node front=root;                        //记录当前Node的前一个Node
  49.                         while(n!=null){
  50.                                 front.next=n.next;                //前一个Node的next指向当前Node的next,等于删掉当前Node
  51.                                 n.next=root;                        //把删掉的当前Node挪到最前面
  52.                                 root=n;                                        //root指向当前Node
  53.                                 n=front.next;                        //下一个Node
  54.                         }
  55.                 }
  56.         }
  57.         public static void main(String[] args){
  58.                 LinkedList l=new LinkedList();
  59.                 l.add(2);
  60.                 l.add(1);
  61.                 l.add(65);
  62.                 l.add(43);
  63.                 l.add(6);
  64.                 l.reverse();
  65.                 l.show();
  66.         }
  67. }

  68. class Node{
  69.         public Node(int value){
  70.                 this.value=value;
  71.         }
  72.         protected int value=0;
  73.         protected Node next=null;
  74. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

回复 使用道具 举报
网上比较多的实现是用C,今天看到坛子里大家对算法题的热衷,就拿出来一起讨论一下用Java实现
回复 使用道具 举报
C的?我的方法可能比较笨 新建一个链表,读一个写一个...
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马