学习数据结构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);  }  }  }

 

在这里的链表咱们写了尾指针!

相关文章
相关标签/搜索