一、概述
线性表是最常用的也是最简单的一种数据结构,而线性表又分为顺序表和链表,顺序表就是Java中的ArrayList集合了,而链表则是对应的是LinkedList。相对来说,线性表的随机访问速度较快,而链表必须要从头节点开始查找;链表的优势在于插入和删除的复杂度较低,时间复杂度为O(n)。一个单链表的示意图如下:
https://www.cnblogs.com/skywang12345/p/3561803.html
一个简单Java单链表的成员域如下:
/* Domain */ private int size; Node Head; /* Node Definition */ class Node <T> { T val; Node<T> next; Node(T x) { val = x; } }
务必谨记节点成员类与链表类的关系。
除单链表外,双向链表也是很常用的一种链表,双链表不仅可以指向后继,还将指向前驱节点,将访问前驱节点的时间复杂度从O(n)将为O(1),性能更加优异,相应的实现也会更加复杂一些,需增加前驱指针。
事实上,还有一种链表不被经常使用,这里做简单介绍——循环链表(circular linked list),特点是最后一个节点的指针指向头节点,这样,单链表也能通过任一节点找到其他所有节点。基本操作和单链表相同,只是遍历时将判空改为判断是否等于头节点。如果将双向链表和循环链表结合一起就产生了循环双向链表或者叫双向循环链表。这样从链表中的一个节点访问另一个节点效率将会十分之高。
注意:一般大家所说的双向链表均为本文中的循环双向链表,我在此引入这些概念只是为了更好的解释和介绍。
/* Domain */
private int size;
Node Head;
Node Tail;
/* Node Definition */
class Node <T>
{
T val;
Node<T> next;
Node<T> prior;
Node(T x) { val = x; }
}
二、链表实现
类
class List <T> { /* Domain */ private int size; Node Head; /* Node Definition */ class Node <T> { T val; Node<T> next; Node(T x) { val = x; } } /* Constructor */ public List() { size = 0; Head = null; } /* Function */ public int len() { return size; } public void add (T v, int i) { Node <T> N = new Node (v); if (i > size || i < 0) { System.out.print("Out of length"); } else if (i == 0) { Head = N; size++; } else { int m=1; Node p = Head; while(m < i) { p = p.next; m++; } N.next = p.next; p.next = N; size++; } } public void delete (int j) { if (j > size || j <= 0) { System.out.print("Out of length"); } else if (j == 1) { Head = Head.next; } else { int m=1; Node p = Head; while(m < j - 1) { p = p.next; m++; } p.next = p.next.next; size--; } } public void print() { System.out.print("Head->"); Node q = Head; while (q!=null) { System.out.print(q.val+"->"); q=q.next; } System.out.print("Tail\n"); } }