學習數據結構Day4

鏈表java

 

以前看過了動態數組,棧和隊列,雖然咱們把第一個叫作動態數組,可是,他們的底層實質上仍是靜態數組。靠node

 

resize來實現動態數組。而鏈表是真正的數據結構數組

 

  • 鏈表須要一個節點。
  • 數據存儲在鏈表中

 

至關因而一串火車,將數據放在車箱中,兩個車箱之間還須要一個個節點來相互串聯。數據結構

 

優勢:實現了真正的動態。app

 

缺點:沒法進行隨機訪問ide

 

public class LinkedList<E> {   private class Node {   public E e;  public Node next;   public Node(E e) {  this(e, null);  }   public Node(E e, Node next) {  this.e = e;  this.next = next;  }   public Node() {  this(null, null);  }   @Override  public String toString() {  return e.toString();  }  }   private Node head;  private int size;   public LinkedList(Node head, int size) {  head = null;  this.size = 0;  }   //獲取鏈表中的元素個數  public int getSize() {  return size;  }   //返回鏈表是否爲空  public boolean isEmpty() {  return size == 0;  }   //鏈表添加新的元素  public void addFirst(E e) { // Node newNode = new Node((E) node); // newNode.next = head; // head = newNode;   head = new Node(e, head);  size++;  }   //在鏈表的index位置添加新的元素e  //在鏈表中不是一個經常使用的操做 :)  public void add(int index, E e) {  if (index < 0 || index > size) {  throw new IllegalArgumentException("Add failed,Illegal index");  }  if (index == 0) {  addFirst(e);  } else {  Node prev = new Node(e);  for (int i = 0; i < index - 1; i++) {  prev.next = prev;  } // Node node = new Node(e); // prev.next = node.next; // prev.next = node;  prev.next = new Node(e,prev.next);   size++;  }  }   //在末尾添加元素  public void addLast(E e){  add(size,e);  } 

 

這是本身創建的鏈表,在此處,必定要注意幾點ui

  • 在增長或刪除元素時,不要忘了維護size
  • 再添加鏈表時,必定不要忘了順序的問題,必定是先prev.next = node.next.以後纔是prev.next = node;
  • 一開始的時候 head = prev

 

再添加操做時,因爲頭結點的上一個節點時null,因此咱們須要特殊處理,爲了解決這個問題,咱們增長了一個虛擬this

 

頭結點。這個節點不存出任何數據。atom

 

public class LinkedList<E> {   private class Node {   public E e;  public Node next;   public Node(E e) {  this(e, null);  }   public Node(E e, Node next) {  this.e = e;  this.next = next;  }   public Node() {  this(null, null);  }   @Override  public String toString() {  return e.toString();  }  }   private Node dummyHead;  private int size;    public LinkedList() {  dummyHead = new Node(null, null);  size = 0;  }   public LinkedList(Node head, int size) {  head = null;  this.size = 0;  }   //獲取鏈表中的元素個數  public int getSize() {  return size;  }   //返回鏈表是否爲空  public boolean isEmpty() {  return size == 0;  }  //在鏈表的index位置添加新的元素e  //在鏈表中不是一個經常使用的操做 :)  public void add(int index, E e) {  if (index < 0 || index > size) {  throw new IllegalArgumentException("Add failed,Illegal index");  }   Node prev = dummyHead;  for (int i = 0; i < index; i++) {  prev.next = prev;  } // Node node = new Node(e); // prev.next = node.next; // prev.next = node;  prev.next = new Node(e, prev.next);   size++;   }  //鏈表添加新的元素  public void addFirst(E e) { // Node newNode = new Node((E) node); // newNode.next = head; // head = newNode;   add(0,e);  size++;  }  //在末尾添加元素  public void addLast(E e) {  add(size, e);  }   } 

 

鏈表的遍歷,增 刪 改 查。spa

 

public class LinkedList<E> {   private class Node {   public E e;  public Node next;   public Node(E e) {  this(e, null);  }   public Node(E e, Node next) {  this.e = e;  this.next = next;  }   public Node() {  this(null, null);  }   @Override  public String toString() {  return e.toString();  }  }   private Node dummyHead;  private int size;    public LinkedList() {  dummyHead = new Node();  size = 0;  }    //獲取鏈表中的元素個數  public int getSize() {  return size;  }   //返回鏈表是否爲空  public boolean isEmpty() {  return size == 0;  }    //在鏈表的index位置添加新的元素e  //在鏈表中不是一個經常使用的操做 :)  public void add(int index, E e) {  if (index < 0 || index > size) {  throw new IllegalArgumentException("Add failed,Illegal index");  }   Node prev = dummyHead;  for (int i = 0; i < index; i++) {  prev= prev.next ;  } // Node node = new Node(e); // prev.next = node.next; // prev.next = node;  prev.next = new Node(e, prev.next);   size++;   }    //鏈表添加新的元素  public void addFirst(E e) { // Node newNode = new Node((E) node); // newNode.next = head; // head = newNode;   add(0, e);   }    //在末尾添加元素  public void addLast(E e) {  add(size, e);  }   /**  * 遍歷整個列表  * 實際過程當中不會這麼用  * 僅供聯繫  *  * @param index  * @return  */  public E get(int index) {  if (index < 0 || index > size) {  throw new IllegalArgumentException("Get failed Illegal index");  }  Node cur = dummyHead.next;  for (int i = 0; i < index; i++) {  cur = cur.next;  }  return cur.e;  }  // 得到鏈表的第一個元素 public E getFirst() { return get(0);  } //獲取鏈表的最後一個元素 public E getLast() { return get(size - 1);  } //修改鏈表的第index(0-based)個位置的元素爲e //在鏈表中不是一個經常使用的操做,練習用 :) public void set(int index, E e) { if (index < 0 || index >= size) { throw new IllegalArgumentException("Set Failed,illegal index");  } Node cur = dummyHead.next; for (int i = 0; i < index; i++) { cur = cur.next;  } cur.e = e;  } //參照鏈表中是否有元素E public boolean contains(E e){ Node cur = dummyHead.next; while (cur != null){ if(cur.e.equals(e)){ return true;  } cur = cur.next;  } return false;  } @Override public String toString(){ StringBuilder res = new StringBuilder(); Node cur = dummyHead.next; while(cur != null){ res.append(cur+"->"); cur = cur.next;  } res.append("null"); return res.toString(); } } 

 

以前這些代碼咱們寫完了增 改 查,下面咱們就要寫刪除操做。

 

 //刪除鏈表中的一個元素  public E remove(int index) {  if (index > 0 || index < size) {  throw new IllegalArgumentException("remove failed");  }  Node prev = dummyHead;  for (int i = 0; i < index; i++) {  prev = prev.next;  }  Node retNode = prev.next;  prev.next = retNode.next;  retNode.next = null;  size--;  return retNode.e;  }   //刪除鏈表中的第一個元素  public E removeFirst() {  return remove(0);  }   //刪除鏈表中最後一個元素  public E removeLast() {  return remove(size - 1);  }

 

鏈表的時間複雜度

 

  • addLast(e):O(n)
  • addFirst(e):O(1)
  • add(index,e):O(n)
  • setIndex(e):O(n)
  • get(index):O(n)
  • contains(e):O(n)

若是隻對鏈表頭進行操做,那麼他的時間複雜度是O(1),因此咱們來嘗試一下利用鏈表來作棧的可能性。

 

import java.util.List;  /**  * @author shkstart  * @create 2019-11-29 13:03  */ public class LinkedListStack<E> implements Stack<E>{   private LinkedList<E> list;   public LinkedListStack() {  list = new LinkedList<E>();  }   @Override  public int getSize() {  return getSize();  }   @Override  public void push(E e) {  list.addFirst(e);  }   @Override  public boolean isEmpty() {  return isEmpty();  }   @Override  public E pop() {  return list.removeFirst();  }   @Override  public E peek() {  return list.getFirst();  }   @Override  public String toString(){  StringBuilder res = new StringBuilder();  res.append("stack:top");  res.append(list);  return res.toString();  }   public static void main(String[] args) {  LinkedListStack<Integer> stack = new LinkedListStack<Integer>();   for (int i = 0; i < 5; i++) {  stack.push(i);  System.out.println(stack);  }   stack.pop();  System.out.println(stack);  } } 

 

作完了棧,一樣的 咱們試驗一下利用鏈表實現隊列。

 

 private class Node {   public E e;  public Node next;   public Node(E e, Node next) {  this.e = e;  this.next = next;  }   public Node(E e) {  this(e, null);  }   public Node() {  this(null, null);  }   @Override  public String toString() {  return e.toString();  }   }   private Node tail, head;   private int size;   public LinkedListQueue(Node tail, Node head, int size) {  this.tail = null;  this.head = null;  this.size = 0;  }   public LinkedListQueue() {  }   @Override  public int getSize() {  return getSize();  }   @Override  public boolean isEmpty() {  return isEmpty();  }   @Override  public void enqueue(E e) {  if (tail.next == null) {  Node node = new Node(e);  tail = head;  } else {  tail.next = new Node(e);  tail = tail.next;  }  size++;  }   @Override  public E dequeue() {   if (isEmpty()) {  throw new IllegalArgumentException("dequeue出錯!");  }   Node ret = head;  head = head.next;  ret.next = null;  if (head == null) {  tail = head;  }  size--;  return ret.e;  }   @Override  public E getFront() {  if (isEmpty()) {  throw new IllegalArgumentException("Queue is empty");  }  return head.e;  }   @Override  public String toString() {  StringBuilder builder = new StringBuilder();  builder.append("Queue:");  builder.append("front [");  Node cur = head;  while (cur != null) {  cur = cur.next;  }  builder.append("Null tail");  return builder.toString();   }    public static void main(String[] args) { LinkedListQueue<Integer> LinkedListQueue = new LinkedListQueue<Integer>(); for (int i = 0; i < 10; i++) { LinkedListQueue.enqueue(i); System.out.println(LinkedListQueue); if (i % 3 == 2) { LinkedListQueue.dequeue(); System.out.println(LinkedListQueue);  }  }  }

 

在這裏的鏈表咱們寫了尾指針!

相關文章
相關標籤/搜索