用链表实现线性表
在实现的时候我们先来说说什么是链表?
其实,链表就像是解密游戏一样,只有到达一个地点,才会有NPC给你下一个地点的地图,从而才能知道下个地点的位置
所以链表也是一样,对于一个链表,一个结点除了要保存结点自身的值以外,还需要保存下一个结点的地址.
这是一个简单链表的单个结点,val代表当前结点存储的值,next是一个引用,指向下一个结点
由于Java中不存在指针,所以结点通常为一个类,而next则是一个结点类实例的引用
可以看到,每一结点都保存了下一个节点的地址,所以,链表不要求每个结点中的地址空间连续
所以如何创建一个链表呢?那么下面我们就来实现
方法接口
定义一个方法接口
public interface ListMethods<T> {
void clear();
boolean isEmpty();
int length();
T get(int i);
void insert(T t);
void insert(int i, T t);
T remove(int i);
int indexOf(T t);
}
创建链表类
public class LinkList<T> {
private Node head; // 头节点
private int N; // 链表元素统计数
// 在类中创建一个私有类
private class Node {
T item; // 用来存储数据元素
Node next; // 定一个Node对象来指向下一个类的地址
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) {
if(head.next == null) {
return null;
}
Node n = head.next;
for (int index = 0; index < i; index++) {
n = n.next;
}
return n.item;
}
向线性表中添加元素t
public void insert(T t) {
Node n = head; // 把头节点复制给一个新元素
while (n.next != null) {
n = n.next;
}
n.next = new Node(t, null);
N++;
}
在i元素处插入元素t
public void insert(int i, T t) {
Node n = head;
for (int index = 0; index < i; index++) {
n = n.next;
}
n.next = new Node(t, n.next);
N++;
}
删除线性表中下标为i的元素
public T remove(int i) {
Node n = head;
for (int index = 0; index < i; index++) {
n = n.next;
}
Node name = n.next;
n.next = name.next;
N--;
return name.item;
}
查找元素t是否在线性表中,如果在则返回下标
public int indexOf(T t) {
Node n = head;
for (int i = 0; n.next != null; i++) {
n = n.next;
if (n.item.equals(t)) {
return i;
}
}
return -1;
}
反转整个链表
/**
* 用来反转整个链表
*/
public void reverse() {
// 判断当前链表是否为空链表
if (isEmpty()) {
return;
}
reverse(head.next);
}
/**
* 反转指定的结点curr, 并把反转后的结点返回
*
* @param curr
* @return
*/
public Node reverse(Node curr) {
if (curr.next == null) {
head.next = curr;
return curr;
}
// 递归的反转当前结点curr的下一个结点,返回值就是链表反转后,当前结点的上一个结点
Node pre = reverse(curr.next);
// 让返回结点的下一个结点变味当前结点curr
pre.next = curr;
// 把当前结点的下一个结点变为null
curr.next = null;
return curr;
}
遍历整个链表
public class LinkList<T> implements ListMethods<T>, Iterable<T> {
.....
@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;
}
}
}
完整代码
package DataStrues.ListTable;
import java.util.Iterator;
public class LinkList<T> implements ListMethods<T>, 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;
}
@Override
public void clear() {
head.next = null;
this.N = 0;
}
@Override
public boolean isEmpty() {
return N == 0;
}
@Override
public int length() {
return N;
}
@Override
public T get(int i) {
if(head.next == null) {
return null;
}
Node n = head.next;
for (int index = 0; index < i; index++) {
n = n.next;
}
return n.item;
}
@Override
public void insert(T t) {
Node n = head; // 把头节点复制给一个新元素
while (n.next != null) {
n = n.next;
}
n.next = new Node(t, null);
N++;
}
@Override
public void insert(int i, T t) {
Node n = head;
for (int index = 0; index < i; index++) {
n = n.next;
}
n.next = new Node(t, n.next);
N++;
}
@Override
public T remove(int i) {
Node n = head;
for (int index = 0; index < i; index++) {
n = n.next;
}
Node name = n.next;
n.next = name.next;
N--;
return name.item;
}
@Override
public int indexOf(T t) {
Node n = head;
for (int i = 0; n.next != null; i++) {
n = n.next;
if (n.item.equals(t)) {
return i;
}
}
return -1;
}
/**
* 用来反转整个链表
*/
public void reverse() {
// 判断当前链表是否为空链表
if (isEmpty()) {
return;
}
reverse(head.next);
}
/**
* 反转指定的结点curr, 并把反转后的结点返回
*
* @param curr
* @return
*/
public Node reverse(Node curr) {
if (curr.next == null) {
head.next = curr;
return curr;
}
// 递归的反转当前结点curr的下一个结点,返回值就是链表反转后,当前结点的上一个结点
Node pre = reverse(curr.next);
// 让返回结点的下一个结点变味当前结点curr
pre.next = curr;
// 把当前结点的下一个结点变为null
curr.next = null;
return curr;
}
@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;
}
}
}