数据结构 实现单向链表

数据结构对于一个程序员来说是必备的知识,虽然之前也了解过这些数据结构,但是总感觉没有达到一个对所有数据结构都了如指掌的境界,于是作者打算手写实现各种数据结构,以便于学习了解这些数据结构的全貌。

对于数据结构的分析如果足够深入,那么必定还要涉及jvm的内存层面,目前本人还没有足够的知识储备,所以只从代码的层面学习理解这些数据结构的实现。

这次先从最简单的单向链表的实现作为开始,单向链表属于最基础的链表结构,它的定义:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。——来自百度百科的介绍

链表结构示意图

用我自己的理解来说,链表就是一个个带链接的节点组成的,每个节点由两部分组成,第一部分是该节点存储的数据,第二部分是该节点的下一个节点的指针。这样的结构我们只需要知道这个链表的头节点,那么我们就能挨个得到整个链表的所有节点。

链表的特点:

没有容量限制
没有扩容的需求
操作两头快,中间慢
线程不安全
链表的操作:

1.插入新节点:将插入位置的节点的上一个节点的Next指针赋值给新插入的节点的Next指针,再将上一个节点的Next指针指向新节点。操作完成。

插入新节点示意图

2.删除节点:将要删除的节点位置的上一个节点的Next指针赋值为要删除节点的Next节点指针即可。

删除节点示意图

由上面的示意图可知,如果是操作链表的头部和尾部,那么操作速度是最快的,如果是在对链表的中间位置进行操作,将对链表进行遍历操作。

说了一堆废话,下面开始用代码说话

链表的代码实现:

package dataStructure;

import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;

/**

  • Created by Viking on 2019/4/7

  • 实现的单向链表的集合

  • 只能从前往后单向遍历

  • 可插入重复元素

  • 实现迭代器遍历集合
    */
    public class MySingleLinkList {

    private transient int modCount = 0;
    private transient int size;
    private Node first;
    private Node last;

    public void addLast(E e){
    linkLast(e);
    }
    public E removeLast(){
    if (size==0) throw new NoSuchElementException();
    return unlinkLast(last);
    }
    public E remove(int index){
    return unlink(index);
    }
    public E getFirst(){
    return first.item;
    }
    public E getLast(){
    return last.item;
    }
    public E get(int index){
    checkElementIndex(index);
    return node(index).item;
    }

    /**

    • 向最后一个元素添加链接.
      /
      private void linkLast(E e) {
      final Node l = last;
      final Node newNode = new Node<>(e, null);
      last = newNode;
      if (l == null)
      first = newNode;
      else
      l.next = newNode;
      size++;
      modCount++;
      }
      /
      *
    • 取消指向最后一个元素的链接.
      */
      private E unlinkLast(Node l) {
      if (firstlast&&first!=null) {
      first = null;
      last = null;
      }else if (first!=null) {
      Node node = first;
      int i = 1;
      while (node.next!=null){
      if (node.next
      l&&i==size-1) {
      node.next = null;
      last = node;
      }else node = node.next;
      i++;
      }
      }
      size--;
      modCount++;
      return l.item;
      }

    /**

    • 取消指定索引的节点
      /
      private E unlink(int index){
      checkElementIndex(index);
      Node cursor;
      if (index0 && indexsize-1){
      cursor = first;
      first = null;
      last = null;
      }else if (index==0) {
      cursor =first;
      first = cursor.next;
      }else if (0 < index && index < size-1){
      Node node = first;
      for (int i =0;i<index-1;i++) node = node.next;
      cursor = node.next;
      node.next = cursor.next;
      }else {
      cursor = last;
      last = node(index-1);
      last.next = null;
      }
      size--;
      modCount++;
      return cursor.item;
      }
      /
      *
    • 判断指定索引是否存在元素.
      /
      private boolean isElementIndex(int index) {
      return index >= 0 && index < size;
      }
      private void checkElementIndex(int index) {
      if (!isElementIndex(index))
      throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
      }
      /
      *
    • 返回指定索引的元素.
      /
      private Node node(int index){
      Node node = first;
      for (int i =0;i<index;i++) node = node.next;
      return node;
      }
      /
      *
    • Constructs an IndexOutOfBoundsException detail message.
    • Of the many possible refactorings of the error handling code,
    • this "outlining" performs best with both server and client VMs.
      */
      private String outOfBoundsMsg(int index) {
      return "Index: "+index+", Size: "+size;
      }
      public int size(){
      return size;
      }
      public boolean isEmpty(){
      return size0;
      }
      public String toString(){
      StringBuilder str = new StringBuilder();
      if (first
      null){
      str.append("[]");
      }else {
      Node next = first;
      str.append("[");
      str.append(first.item);
      while (next.next!=null){
      next = next.next;
      str.append(",");
      str.append(next.item);
      }
      str.append("]");
      }
      return str.toString();
      }

    /**

    • 链表的节点
      */
      private static class Node {
      E item;
      Node next;

      Node(E element, Node next) {
      this.item = element;
      this.next = next;
      }
      }

    public Iterator myIterator(){
    return new MyIterator(0);
    }
    public Iterator myIterator(int index){
    return new MyIterator(index);
    }

    /**

    • 实现迭代器遍历容器
      */
      private class MyIterator implements Iterator{
      private Node lastReturned;
      private Node next;
      private int nextIndex;
      private int expectedModCount = modCount;
      private MyIterator(int index){
      next = index == size ? null : node(index);
      nextIndex = index;

      }
      @Override
      public boolean hasNext() {
      return nextIndex < size;
      }

      @Override
      public E next() {
      checkForComodification();
      if (!hasNext())
      throw new NoSuchElementException();

       lastReturned = next;
       next = next.next;
       nextIndex++;
       return lastReturned.item;
      

      }

      @Override
      public void remove() {
      checkForComodification();
      if (lastReturned == null)
      throw new IllegalStateException();

       Node<E> lastNext = lastReturned.next;
       unlink(nextIndex-1);
       if (next == lastReturned)
           next = lastNext;
       else
           nextIndex--;
       lastReturned = null;
       expectedModCount++;
      

      }

      @Override
      public void forEachRemaining(Consumer<? super E> action) {
      Objects.requireNonNull(action);
      while (modCount == expectedModCount && nextIndex < size) {
      action.accept(next.item);
      lastReturned = next;
      next = next.next;
      nextIndex++;
      }
      checkForComodification();
      }
      final void checkForComodification() {
      if (modCount != expectedModCount)
      throw new ConcurrentModificationException();
      }
      }
      }
      实现方式我是参考了LinkedList的源码,LinkedList是双向链表实现的。

编写一个测试类:

import dataStructure.MySingleLinkList;

import java.util.*;

/**

  • Created by Viking on 2019/4/7
    */
    public class TestSList {
    public static void main(String[] args) {
    MySingleLinkList sList = new MySingleLinkList<>();
    System.out.println(sList.size());
    System.out.println(sList);
    sList.addLast("Hello!");
    sList.addLast("My");
    sList.addLast("Link");
    sList.addLast("List");
    sList.addLast("last");
    sList.addLast("same");
    sList.addLast("same");
    System.out.println(sList.size());
    System.out.println(sList.isEmpty());
    System.out.println(sList);
    System.out.println("index of 0:"+sList.get(0));
    System.out.println("index of 1:"+sList.get(1));
    System.out.println("index of 2:"+sList.get(2));
    System.out.println("index of 3:"+sList.get(3));
    System.out.println("index of 4:"+sList.get(4));
    System.out.println("getFirst:"+sList.getFirst());
    System.out.println("getLast:"+sList.getLast());
    System.out.println(sList);
    System.out.println(sList.removeLast());
    System.out.println("After remove 1 element:size="+sList.size());
    System.out.println(sList.removeLast());
    System.out.println("After remove 2 element:size="+sList.size());
    System.out.println(sList.removeLast());
    System.out.println("After remove 3 element:size="+sList.size());
    System.out.println(sList.removeLast());
    System.out.println("After remove 4 element:size="+sList.size());
    System.out.println(sList.removeLast());
    System.out.println("After remove 5 element:size="+sList.size());
    System.out.println(sList);
    sList.addLast("iterator");
    sList.addLast("is");
    sList.addLast("cool");
    Iterator stringIterator = sList.myIterator();
    // while (stringIterator.hasNext()){
    // System.out.println(stringIterator.next());
    // }
    // System.out.println(sList);

     int i =0;
     while (stringIterator.hasNext()){//一迭代器对象只能执行一次迭代
         System.out.println(stringIterator.next());
         if (i<3) stringIterator.remove();
         i++;
    

// if (sList.size()==1) break;
}
System.out.println(sList);
}
}
测试结果:

0
[]
7
false
[Hello!,My,Link,List,last,same,same]
index of 0:Hello!
index of 1:My
index of 2:Link
index of 3:List
index of 4:last
getFirst:Hello!
getLast:same
[Hello!,My,Link,List,last,same,same]
same
After remove 1 element:size=6
same
After remove 2 element:size=5
last
After remove 3 element:size=4
List
After remove 4 element:size=3
Link
After remove 5 element:size=2
[Hello!,My]
Hello!
My
iterator
is
cool
[is,cool]
 
————————————————
版权声明:本文为CSDN博主「·Diablo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mr__Viking/article/details/89450613

posted @ 2020-03-26 23:30  东东dillon  阅读(181)  评论(0编辑  收藏  举报