什么是线性表
线性表是最基本、最简单和最常用的一种数据结构,一个线性表是n个具有相同特性的数据元素的有限序列。
若A元素在B元素前面,则称A为B的前驱元素;若B元素在A元素的后面,则称B为A的后继元素。
线性表的特征:数据元素之间存在一对一的关系
第一个数据元素没有前驱元素,叫头结点。
最后一个数据元素没有后继元素,叫尾结点。
除了头尾结点,其它数据元素有且仅有一个前驱元素和后继元素。
线性表的分类
按照数据的存储方式可以分为顺序表和链表。
什么是链表
链表中的元素在内存中不连续,查询慢(查询任何数据都要从头开始找),但增删快,分为单链表和双链表。
本节内容包括单链表和双链表的实现、链表反转、快慢指针、循环链表(尾结点指向第一个数据结点)、约瑟夫问题。

单链表实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
| import java.util.Iterator;
public class LinkList<T> implements Iterable<T> { private Node head; private int N;
private class Node { T item; Node next;
public Node(T item, Node next) { this.item = item; this.next = next; } }
public LinkList() { this.head = new Node(null, null); this.N = 0; }
public void clear() { head.next = null; this.N = 0; }
public boolean isEmpty() { return N == 0; }
public int length() { return N; }
public T get(int i) { Node n = head; for (int index = 0; index < i; index++) { n = n.next; } return n.item; }
public void add(T t) { Node n = head; while (n.next != null) { n = n.next; } Node newNode = new Node(t, null); n.next = newNode; this.N++; }
public void insert(int i, T t) { Node pre = head; for (int index = 0; index < i - 1; index++) { pre = pre.next; } Node temp = pre.next; Node tNode = new Node(t, temp); pre.next = tNode; this.N++; }
public T remove(int i) { Node pre = head; for (int index = 0; index < i - 1; index++) { pre = pre.next; } Node temp = pre.next; pre.next = temp.next; this.N--; return temp.item; }
public int indexOf(T t) { Node n = head; for (int i = 1; n.next != null; i++) { n = n.next; if (n.item.equals(t)) { return i; } } return -1; }
@Override public Iterator<T> iterator() { return new LIterator(); }
private class LIterator implements Iterator { private Node n;
public LIterator() { this.n = head; }
@Override public boolean hasNext() { return n.next != null; }
@Override public Object next() { n = n.next; return n.item; } }
public void reverse() { if (isEmpty()) { return; } reverse(head.next); }
public Node reverse(Node curr) { if (curr.next == null) { head.next = curr; return curr; } Node pre = reverse(curr.next); pre.next = curr; curr.next = null; return curr; } }
|
双链表实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
| import java.util.Iterator;
public class TwoWayLinkList<T> implements Iterable<T> { private Node head; private Node last; private int N;
private class Node { T item; Node pre; Node next;
public Node(T item, Node pre, Node next) { this.item = item; this.pre = pre; this.next = next; } }
public TwoWayLinkList() { this.head = new Node(null, null, null); this.last = null; this.N = 0; }
public void clear() { head.next = null; last = null; this.N = 0; }
public boolean isEmpty() { return N == 0; }
public int length() { return N; }
public T getFirst() { if (isEmpty()) { return null; } return head.next.item; }
public T getLast() { if (isEmpty()) { return null; } return last.item; }
public T get(int i) { Node n = head; for (int index = 0; index < i; index++) { n = n.next; } return n.item; }
public void add(T t) { if (isEmpty()) { Node newNode = new Node(t, head, null); head.next = newNode; last = newNode; } else { Node newNode = new Node(t, last, null); last.next = newNode; last = newNode; } this.N++; }
public void insert(int i, T t) { Node pre = head; for (int index = 0; index < i - 1; index++) { pre = pre.next; } Node temp = pre.next; Node tNode = new Node(t, pre, temp); pre.next = tNode; temp.pre = tNode; this.N++; }
public T remove(int i) { Node pre = head; for (int index = 0; index < i - 1; index++) { pre = pre.next; } Node temp = pre.next; Node nextNode = temp.next; pre.next = nextNode; if (nextNode != null) { nextNode.pre = pre; } this.N--; return temp.item; }
public int indexOf(T t) { Node n = head; for (int i = 1; n.next != null; i++) { n = n.next; if (n.item.equals(t)) { return i; } } return -1; }
@Override public Iterator<T> iterator() { return new LIterator(); }
private class LIterator implements Iterator { private Node n;
public LIterator() { this.n = head; }
@Override public boolean hasNext() { return n.next != null; }
@Override public Object next() { n = n.next; return n.item; } } }
|