链表
本篇博客主要是自己实现一下链表。
链表的节点:
//节点类
class ListNode {
public int data;
public ListNode next;
public ListNode random;
//构造方法
public ListNode(int data) {
this.data = data;
this.next = null;
this.random=null;
}
}
创建链表的类:
该链表为不带头结点的单链表,并且里边有很多链表基本操作的实例方法,下面一一介绍。
public class MySignalList {
//此时的头随时可能变化
public ListNode head;
//构造方法
public MySignalList() {
this.head = null;
}
}
插入元素:头插法
public void addFirst(int data) {
//创建一个新的节点
ListNode node = new ListNode(data);
//判断头是否为空(即判断是否为第一次插入,新的单链表的head是空)
if (this.head == null) {
this.head = node;
} else {//不是第一次插入
node.next = this.head;
this.head = node;
}
}
尾插法(也要分是否为第一次插入)
//尾插法(也要分是否为第一次插入)
public void addLast(int data) {
ListNode node = new ListNode(data);
ListNode cur = this.head;
//判断是否为空(即是否为第一次插入)
if (this.head == null) {
this.head = node;
} else {
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
获取单链表的长度
public int getLength() {
int count = 0;
ListNode cur = this.head;
if (this.head == null)
return 0;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
在任意位置插入(第一个数据节点的下标为0)
public boolean addIndex(int index, int data) {
//先判断index的位置是否合法
if (index < 0 || index > this.getLength()) {
System.out.println("该位置不合法!!");
return false;
}
//如果在0号下标插,即第一个位置,直接调用头插法的方法
if (index == 0) {
addFirst(data);
return true;
}
int count = 0;
ListNode cur = this.head;
ListNode node = new ListNode(data);
while (count < index - 1) {
cur = cur.next;
count++;
}
node.next = cur.next;
cur.next = node;
return true;
}
打印链表
public void display1() {
//从头开始
ListNode cur = this.head;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
public void display2(ListNode head) {
ListNode cur = head;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
查找前驱
public ListNode searchPrev(int key) {
ListNode pre = this.head;
while (pre.next != null) {
if (pre.next.data == key) {
return pre;
}
pre = pre.next;
}
return null;
}
删除第一次出现关键字为key的节点
public void remove(int key) {
if (this.head == null) {
System.out.println("单链表为空");
return;
}
//删除的节点是否是头结点
if (this.head.data == key) {
this.head = this.head.next;
return;
}
//1.找到key的前驱
ListNode prev = searchPrev(key);
if (prev == null) {
return;
}
//2.删除节点
prev.next = prev.next.next;
}
查找关键字key是否在单链表中
public boolean contains(int key) {
ListNode cur = this.head;
while (cur != null) {
if (cur.data == key) {
return true;
}
cur = cur.next;
}
return false;
}
//删除所有值为key的节点
public ListNode removeAllKey(int key) {
//判断链表是否为空
if (this.head == null) {
return null;
}
ListNode pre = this.head;
ListNode cur = pre.next;
while (cur != null) {
if (pre.next.data == key) {
pre.next = cur.next;
cur = cur.next;
}
if (pre.next.data != key) {
pre = cur;
cur = cur.next;
}
}
//判断头节点是否要删除
if (this.head.data == key) {
this.head = this.head.next;
}
return this.head;
}
删除所有值为key的节点
public ListNode removeAllKey(int key) {
//判断链表是否为空
if (this.head == null) {
return null;
}
ListNode pre = this.head;
ListNode cur = pre.next;
while (cur != null) {
if (pre.next.data == key) {
pre.next = cur.next;
cur = cur.next;
}
if (pre.next.data != key) {
pre = cur;
cur = cur.next;
}
}
//判断头节点是否要删除
if (this.head.data == key) {
this.head = this.head.next;
}
return this.head;
}
反转一个单链表——头插法
//反转一个单链表
//发一:头插法
//法二:三个引用改变指向
public ListNode reverseList() /**/{
ListNode prev = null;
ListNode cur = this.head;
ListNode NewHead = null;
if (this.head == null) {
return null;
}
while (cur != null) {
ListNode curNext = cur.next;
if (curNext == null) {
NewHead = cur;
}
cur.next = prev;
prev = cur;
cur = curNext;
// curNext=cur.next;
}
return NewHead;
}
反转一个单链表——三个引用改变指向法
public void reverseList2()
{
ListNode cur=this.head;
ListNode tmp=new ListNode(-1);
while(cur!=null)
{
ListNode curNext=cur.next;
curNext.next=cur;
cur=curNext;
}
}
查找链表中间节点(快慢指针法)
思路:慢指针一次走一步,快指针一次走两步
public ListNode middleNode() {
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
查找链表中倒数第k个节点
思路:快慢指针,快指针先走k步,再一人一步向前走,直到快指针为空
//查找链表中倒数第k个节点:快慢指针
public ListNode FindKthKey(int k) {
if (k < 0) {
return null;
}
ListNode fast = this.head;
ListNode slow = this.head;
while (k - 1 > 0) {
if (fast.next != null) {
fast = fast.next;
k--;
} else {
System.out.println("没有这个节点");
return null;
}
}
while (fast.next != null) {
slow = slow.next;
fast = fast.next;
}
return slow;
}