Java实现链表(单向和双向)

单向链表:

  1. package LinkedList;     
  2.     
  3. /**   
  4.  * <p><strong>我的Java单链表练习</strong></p>   
  5.  * <p>单链表提供了在列表头的高效插入和删除操作,不过在单链表的末尾的插入操作效率很低.</p>   
  6.  * <p>单链表指针域保存着下一节点的引用,尾结点的指针域等于null</p>   
  7.  * @author baby69yy2000   
  8.  */    
  9. public class SingleLinkedList<T> {     
  10.          
  11.     /**   
  12.      * 结点类   
  13.      */    
  14.     private static class Node<T> {     
  15.         T nodeValue; // 数据域     
  16.         Node<T> next; // 指针域保存着下一节点的引用     
  17.              
  18.         Node(T nodeValue, Node<T> next) {     
  19.             this.nodeValue = nodeValue;     
  20.             this.next = next;     
  21.         }     
  22.              
  23.         Node(T nodeValue) {     
  24.             this(nodeValue, null);     
  25.         }     
  26.     }     
  27.     
  28.     // 下面是SingleLinkedList类的数据成员和方法     
  29.     private Node<T> head, tail;     
  30.          
  31.     public SingleLinkedList() {     
  32.         head = tail = null;     
  33.     }     
  34.          
  35.     /**   
  36.      * 判断链表是否为空   
  37.      */    
  38.     public boolean isEmpty() {     
  39.         return head == null;     
  40.     }     
  41.          
  42.     /**   
  43.      * 创建头指针,该方法只用一次!   
  44.      */    
  45.     public void addToHead(T item) {     
  46.         head = new Node<T>(item);     
  47.         if(tail == null) tail = head;     
  48.     }     
  49.          
  50.     /**   
  51.      * 添加尾指针,该方法使用多次   
  52.      */    
  53.     public void addToTail(T item) {     
  54.         if (!isEmpty()) { // 若链表非空那么将尾指针的next初使化为一个新的元素     
  55.             tail.next = new Node<T>(item); // 然后将尾指针指向现在它自己的下一个元素     
  56.             tail = tail.next;     
  57.         } else { // 如果为空则创建一个新的!并将头尾同时指向它     
  58.             head = tail = new Node<T>(item);           
  59.         }     
  60.     }     
  61.          
  62.     /**   
  63.      * 打印列表   
  64.      */    
  65.     public void printList() {     
  66.         if (isEmpty()) {     
  67.             System.out.println("null");     
  68.         } else {     
  69.             for(Node<T> p = head; p != null; p = p.next)     
  70.                 System.out.println(p.nodeValue);     
  71.         }     
  72.     }     
  73.          
  74.     /**   
  75.      * 在表头插入结点,效率非常高   
  76.      */    
  77.     public void addFirst(T item) {     
  78.         Node<T> newNode = new Node<T>(item);     
  79.         newNode.next = head;     
  80.         head = newNode;     
  81.     }     
  82.          
  83.     /**   
  84.      * 在表尾插入结点,效率很低   
  85.      */    
  86.     public void addLast(T item) {     
  87.         Node<T> newNode = new Node<T>(item);     
  88.         Node<T> p = head;     
  89.         while (p.next != null) p = p.next;     
  90.         p.next = newNode;     
  91.         newNode.next = null;     
  92.     }     
  93.          
  94.     /**   
  95.      * 在表头删除结点,效率非常高   
  96.      */    
  97.     public void removeFirst() {     
  98.         if (!isEmpty()) head = head.next;     
  99.         else System.out.println("The list have been emptied!");     
  100.     }     
  101.          
  102.     /**   
  103.      * 在表尾删除结点,效率很低   
  104.      */    
  105.     public void removeLast() {     
  106.         Node<T> prev = null, curr = head;     
  107.         while(curr.next != null) {     
  108.             prev = curr;     
  109.             curr = curr.next;     
  110.             if(curr.next == null) prev.next = null;     
  111.         }     
  112.     }     
  113.          
  114.     /**   
  115.      * <p>插入一个新结点</p>   
  116.      * <ul>插入操作可能有四种情况:   
  117.      * <li>①表为空, 返回false</li>   
  118.      * <li>②表非空,指定的数据不存在</li>   
  119.      * <li>③指定的数据是表的第一个元素</li>   
  120.      * <li>④指定的数据在表的中间</li></ul>   
  121.      * @param appointedItem 指定的nodeValue   
  122.      * @param item 要插入的结点   
  123.      * @return 成功插入返回true;   
  124.      */    
  125.     public boolean insert(T appointedItem, T item) {     
  126.         Node<T>  prev = head, curr = head.next, newNode;     
  127.         newNode = new Node<T>(item);     
  128.         if(!isEmpty()) {     
  129.             while((curr != null) && (!appointedItem.equals(curr.nodeValue))) { //两个判断条件不能换     
  130.                 prev = curr;     
  131.                 curr = curr.next;     
  132.             }     
  133.             newNode.next = curr; //②③④     
  134.             prev.next = newNode;     
  135.             return true;      
  136.         }     
  137.         return false//①     
  138.     }     
  139.          
  140.     /**   
  141.      * <p>移除此列表中首次出现的指定元素</p>   
  142.      * <ul>删除操作可能出现的情况:   
  143.      * <li>①prev为空,这意味着curr为head. head = curr.next; --> removeFirst();</li>   
  144.      * <li>②匹配出现在列表中的某个中间位置,此时执行的操作是 --> prev.next = curr.next;,</li></ul>   
  145.      * <p>在列表中定位某个结点需要两个引用:一个对前一结点(prev左)的引用以及一个对当前结点(curr右)的引用.</p>   
  146.      * prev = curr;   
  147.      * curr = curr.next;   
  148.      */    
  149.     public void remove(T item) {     
  150.         Node<T> curr = head, prev = null;     
  151.         boolean found = false;     
  152.         while (curr != null && !found) {     
  153.             if (item.equals(curr.nodeValue)) {     
  154.                 if(prev == null) removeFirst();     
  155.                 else prev.next = curr.next;     
  156.                 found = true;     
  157.             } else {     
  158.                 prev = curr;     
  159.                 curr = curr.next;     
  160.             }     
  161.         }     
  162.     }     
  163.          
  164.     /**   
  165.      * 返回此列表中首次出现的指定元素的索引,如果列表中不包含此元素,则返回 -1.   
  166.      */    
  167.     public int indexOf(T item) {     
  168.         int index = 0;     
  169.         Node<T> p;     
  170.         for(p = head; p != null; p = p.next) {     
  171.             if(item.equals(p.nodeValue))     
  172.                 return index;     
  173.             index++;     
  174.                      
  175.         }     
  176.         return -1;     
  177.     }     
  178.          
  179.     /**   
  180.      * 如果此列表包含指定元素,则返回 true。   
  181.      */    
  182.      public boolean contains(T item) {     
  183.          return indexOf(item) != -1;     
  184.      }     
  185.          
  186.     public static void main(String[] args) {     
  187.         SingleLinkedList<String> t = new SingleLinkedList<String>();     
  188.         t.addToHead("A");     
  189.         //t.addFirst("addFirst");     
  190.         t.addToTail("B");     
  191.         t.addToTail("C");     
  192.         System.out.println(t.indexOf("C")); // 2     
  193.         System.out.println(t.contains("A")); // true     
  194.         //t.addLast("addLast");     
  195.         //t.removeLast();     
  196.         //t.insert("B", "insert");     
  197.         //t.removeFirst();     
  198.         //t.remove("B"); // A C     
  199.         t.printList(); // A B C     
  200.              
  201.     }     
  202.     
  203. }   
****************************************************************************************************************************************************************************

双向链表

package datastruct;

/*
*双向链表的的结点
*/
public class DoubleNode {
private DoubleNode previous;// 指向前一个接点的指针
private int value;// 接点保存的值
private DoubleNode next;// 指向下一个接点的指针



public DoubleNode(int value) {
  super();
  this.value = value;
  this.previous = this;//初始时指向自身
this.next = this;//初始时指向自身
}

public DoubleNode() {
  // TODO Auto-generated constructor stub
}

public DoubleNode getPrevious() {
  return previous;
}

public void setPrevious(DoubleNode previous) {
  this.previous = previous;
}

public int getValue() {
  return value;
}

public void setValue(int value) {
  this.value = value;
}

public DoubleNode getNext() {
  return next;
}

public void setNext(DoubleNode next) {
  this.next = next;
}

}

package datastruct;
/**
* 双向链表
* @author dell
*
*/
public class MyDoubleList {

private DoubleNode head;// 头结点,初始值为null
private int length = 0;// 链表的长度

public int getLength() {
  return length;
}

public void setLength(int length) {
  this.length = length;
}

public MyDoubleList() {
  head = new DoubleNode();
}

public DoubleNode getHead() {
  return head;
}

public void setHead(DoubleNode head) {
  this.head = head;
}

/**
  * @param args
  */
public static void main(String[] args) {
  MyDoubleList ml = new MyDoubleList();
  ml.add(new DoubleNode(1));
  ml.add(new DoubleNode(2));
  ml.add(new DoubleNode(3));
  ml.add(new DoubleNode(4));
  ml.add(new DoubleNode(5));
  ml.add(new DoubleNode(6));
  ml.add(new DoubleNode(7));
  ml.remove(new DoubleNode(3));
   ml.insert(new DoubleNode(11), 3);

  while (ml.head != null) {
   System.out.println(ml.head.getValue());
   ml.head = ml.head.getPrevious();
  }
}

/**
  * 添加新节点
*
  * @param n要加入的节点
*/
public void add(DoubleNode n) {
  head.setNext(n);//头结点的next指针指向n
  //n的前驱指针指向head
  n.setPrevious(head);
  head = n;// 指针移动
this.length++;
}

/**
  * 删除某个节点
*
  * @param n要删除的节点
*/
public void remove(DoubleNode n) {
  if (head == null)
   return;
  if (n.getValue() == this.head.getValue()) {
   head = head.getPrevious();
   head.setNext(null);
   // head.setp
   return;
  }

  DoubleNode pre = head;// 当前节点,初始值为头结点
DoubleNode cur = head.getPrevious();// 当前节点的前驱节点
while (cur != null) {
   if (cur.getValue() == n.getValue()) {
    pre.setPrevious(cur.getPrevious());
    cur.getPrevious().setNext(pre);
    // pre.getNext().setNext(cur.getNext());
    return;//
   }

   pre = pre.getPrevious();// 移动指针
cur = cur.getPrevious();// 移动指针
}

}

/**
  *插入节点
*/
public void insert(DoubleNode n, int i) {
  if (head == null) {
   add(n);
   return;
  }

  DoubleNode pre = head;
  DoubleNode cur = head.getPrevious();
  int j = 1;
  while (cur != null) {
   if (j == i-1) {
    cur.setNext(n);
    n.setPrevious(cur);
    n.setNext(pre);
    pre.setPrevious(n);
    return;
   }

   pre = pre.getPrevious();// 移动指针
cur = cur.getPrevious();// 移动指针
j++;
  }

}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值