学习笔记之关于JAVA实现链表的基本功能

  链表,一个令人熟悉的名词,相信很多人第一次接触这个词是在数据结构的书上。而且大部分这样的书采取了C语言来作为教学代码,很少采取C++,JAVA,C#等面向对象的语言(估计是用不上吧,而且这些面向对象的类,继承等名词又会让初学者容易混淆,毕竟大家很多都是从C语言开始走上编程之路的)。

      之前我有面试过一家公司,有道题目是关于用JAVA去实现链表。那时候我懵了,因为那时候我对java的理解也是到很浅的阶段,引用什么的概念都很陌生,虽然学过数据结构,但是书上教学的是使用了指针,但是JAVA并没有指针这个名词啊,然后擅自用C语言的语法去答题,然后......然后就没有然后了。

     指针究竟是什么?链表的指针又代表了什么含义?这就是解题的具体思路。在java中,是用了引用来答题指针的功能,不过区别就是指针在指向目标地址的同时本身也占有内存,而引用就是单纯的指向一块内存。

  先说说链表结构,通常包含表头,节点1,节点2...节点n,其中节点又包含了数据内容和下个节点的地址。和数组结构(应该叫做顺序表吧大概......)不一样,链表并不用占据连续的内存,它们的区别就不多说了,相信大家都知道。  

  说说怎么实现吧,既然要用引用的方式来代替指针,那么就需要一个特别的类结构:需要同名的成员保存下一个节点的信息。

  public class Node {

      private String data;
      private Node nextNode;

     public String getData() {
          return data;
      }

      public void setData(String data) {
          this.data = data;
      }

      public Node getNextNode() {
          return nextNode;
      }

      public void setNextNode(Node nextNode) {
          this.nextNode = nextNode;
      }

  }

  该怎么使用呢?让我们来初始化一个链表吧!

  private Node InitNode() {
        // 当前节点
        Node curNode = new Node();

        // 构建头结点
        Node head = new Node();
        head.setData("head");
        head.setNextNode(null);
        // 当前节点位于头结点
        curNode = head;

        // 新增第一个节点
        Node n1 = new Node();
        // 获取到当前节点,使得的下一个节点设置为n1
        curNode.setNextNode(n1);
        n1.setData("node1");
        n1.setNextNode(null);
        // 当前节点位于第一个节点
        curNode = n1;

        // 第二个节点
        Node n2 = new Node();
        curNode.setNextNode(n2);
        n2.setData("node2");
        n2.setNextNode(null);
        curNode = n2;

        // 第三个节点
        Node n3 = new Node();
        curNode.setNextNode(n3);
        n3.setData("node3");
        n3.setNextNode(new Node());
        curNode = n3;

        // 第四个节点
        Node n4 = new Node();
        curNode.setNextNode(n4);
        n4.setData("node4");
        n4.setNextNode(new Node());
        curNode = n4;
        return head;
    }

 

  注意curNode的变动,使得当前节点总落在最后一个节点上,下次插入时就不需要知道前面一个节点的名字了,通过curNode就可以直接插入了。

  到底成功了没有,我们来遍历一下。这个遍历和C语言的很相似:

  LinkMain m = new LinkMain();
        Node testNode = m.InitNode();
        Node iter = testNode.getNextNode();
        while (null != iter) {
            if (null != iter.getData()) {
                System.out.println(iter.getData());
            }
            iter = iter.getNextNode();
        }

  输出结果如下:,其中testNode是这样的:

  是不是和C语言很像呢?

  ----------------------------分割线---------------------------------------

  OK,搞定了初始化和遍历,让我们来试试插入一个节点吧,需求是在某个链表中,第N个位置插入一个节点temp:

  新增原理:对于temp节点来说

  红色代表的是之前连接,黑色的是之后应该做的。

  private Node addNode(Node head, int n, Node temp) {
        int i = 0;
        while (null != head) {
            if (i == n) {
                temp.setNextNode(head.getNextNode());
                head.setNextNode(temp);
                return head;
            } else {
                head = head.getNextNode();
                i++;

            }
        }
        return head;
    }

 新增后再遍历一下

    // 新增一个节点
        Node temp = new Node();
        temp.setData("tempNode");
        temp.setNextNode(null);
        Node n3 = m.addNode(testNode, 2, temp);

        iter = testNode.getNextNode();
        while (null != iter) {
            if (null != iter.getData()) {
                System.out.println(iter.getData());
            }
            iter = iter.getNextNode();
        }

   那么效果如何呢?

 

 其中testNode的内容应该是

  

  OK,结果正确。

------------------------------------快下班了,下次来试试删除的功能-----------------------------------------

链表的删除节点功能
        一开始还搞不定删除,后来画图分析了下,终于解决,放上代码。

难点是设置P,Q两点的指向。其中q是p的下个节点。

应该先找到需要删除的位置。

  原理很简单,就是要绕过q来连接p和后后(q后面的节点)节点。  

  删除前:

 

  删除后:

----------------------------

哈哈解决了这个问题真是舒服。

 

 

   

 

  

posted on 2013-12-27 17:17  诺亚行者  阅读(4788)  评论(0编辑  收藏  举报

导航