java实现数据结构单链表
import java.util.Iterator;
import java.util.Objects;
public class LinkList<T> implements Iterable<T> {//实现Iterable接口,重写iterator方法
//记录首结点
private Node1<T> head;
//记录链表的长度
private int N;
public LinkList() {
//初始化数据
this.head = new Node1(null, null);
this.N = 0;
}
//获取第一个元素节点,也就是头结点的下一个节点
public Node1<T> getNode() {
return head.next;
}
//:判断线性表是否为空,是返回true,否返回false
public boolean isEmpty() {
return N == 0;
}
//获取线性表中元素的个数
public int length() {
return N;
}
//空置线性表
public void clear() {
head.item = null;
head.next = null;
N = 0;
}
//读取并返回线性表中的第i个元素的值
public T getItem(int i) {
if (i < 0 || i >= N) {
throw new RuntimeException("元素位置非法!");
}
Node1<T> n = head.next;
for (int index = 0; index < i; index++) {
n = n.next;
}
return n.item;
}
//往线性表中添加一个元素
public void add(T t) {
Node1<T> node = head;
for (int i = 0; node.next != null; i++) {
//找到线性表的最后一个节点后停止
node = node.next;
}
//新建一个节点
Node1<T> newNode = new Node1<>(t, null);
//将新节点添加到当前链表的最后一个节点的next指针域
node.next = newNode;
//长度加一
N++;
}
//在线性表的第i个元素之前插入一个值为t的数据元素
public void insert(int i, T t) {
if (i < 0 || i >= N) {
throw new RuntimeException("插入位置非法");
}
//找到i前面的节点,
Node1<T> NodePrev = head;
for (int index = 0; index < i; index++) {
//结束的nodeHead节点就是要插入的i节点前面的一个节点
NodePrev = NodePrev.next;
}
// 找到i节点,
Node1 curr = NodePrev.next;
//构建新的节点,并让该新节点的next指向i节点
Node1<T> newNode = new Node1<>(t, curr);
//让i之前的节点指向新节点
NodePrev.next = newNode;
//长度加一
N++;
}
//删除并返回线性表中第i个数据元素
public T remove(int i) {
if (i < 0 || i >= N) {
throw new RuntimeException("位置不合法");
}
//获取头结点
Node1<T> prev = head;
//找到i节点的前一个节点
for (int index = 0; index < i; index++) {
prev = prev.next;
}
//获取i节点
Node1<T> curr = prev.next;
//删除i节点,让i节点的前一个节点指向i节点的下一个节点
prev.next = curr.next;
//长度减一
N--;
return curr.item;
}
//返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1。
public int indexOf(T t) {
//找到头结点
Node1<T> prev = head;
//遍历链表,找t元素
for (int i = 0; prev.next != null; i++) {
prev = prev.next;
if (prev.item.equals(t)) {
return i;
}
}
//没有找到返回-1
return -1;
}
@Override
public Iterator<T> iterator() {
return new TIterator();
}
private class TIterator<T> implements Iterator<T> {
private Node1<T> node;
public TIterator() {
this.node = (Node1<T>) head;
}
@Override
public boolean hasNext() {
return node.next != null;
}
@Override
public T next() {
node = node.next;
return node.item;
}
}
//链表的反转
/**
* 采用递归的方式,时间复杂度O(n),空间复杂度O(n)
*/
public void reverse() {
if (isEmpty()) {
return;
}
reverse(head.next);
}
/**
* @param curr 当前遍历的节点
* @return 反转后 ,头结点应该指向原链表的最后一个元素
*/
public Node1<T> reverse(Node1<T> curr) {
//到了最后一个元素
if (curr.next == null) {
//反转后,头结点应该指向原链表中的最后一个元素
head.next = curr;
return curr;
}
//递归返回的当前节点的下一个节点,就是链表反转后当前节点的上一个节点
Node1<T> prev = reverse(curr.next);
prev.next = curr;
//当前结点的下一个结点设为null
curr.next = null;
//返回当前结点
return curr;
}
/**
* 利用快慢指针求链表的中间值
* 快指针的速度是慢指针的两倍
*
* @param first 传递第一个元素节点,也就是头结点的下一个节点
* @return 返回链表的中间值
*/
public T getMiddle(Node1<T> first) {
//定义慢指针
Node1<T> slow = first;
//定义快指针
Node1<T> fast = first;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow.item;
}
/**
* 快慢指针判断链表中是否有环
*
* @param first 第一个元素节点,也就是首元结点
* @return true表示有环,反之无环
*/
public boolean isCircle(Node1<T> first) {
//定义快慢指针
Node1<T> fast = first;
Node1<T> slow = first;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast.equals(slow)) {
return true;
}
}
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LinkList<?> linkList = (LinkList<?>) o;
return N == linkList.N &&
Objects.equals(head, linkList.head);
}
}