class Node {
public int data;//0
public Node next;//null
public Node(int data) {
this.data = data;
this.next = null;
}
}
public class MyLinkedList {
public Node head;//保存单链表的头节点的引用 null
//1.头插法-将一个data插入到单链表的头部
public void addFirst(int data) {
Node node = new Node(data);//将data生成节点
//第一次插入节点
if (this.head == null) {
this.head = node;
return;
}
node.next = this.head;//单链表的插入,要先绑定后面节点的地址
head = node;
}
//2.打印单链表
public void display(){
Node cur = this.head;
while(cur != null){
System.out.print(cur.data+" ");
cur = cur.next;
}
System.out.println();
}
//3.尾插法
public void addLast(int data) {
Node node = new Node(data);
if (this.head == null) {
this.head = node;
return;
}
Node cur = this.head;
while(cur.next != null){
cur = cur.next;
}
cur.next = node;
}
//4.查找关键字key是否在单链表中
public boolean contains(int key) {
Node cur = this.head;
while(cur != null) {
if (cur.data == key) {
return true;
}
cur = cur.next;
}
return false;
}
//5.得到单链表的长度
public int size() {
int count = 0;
Node cur = this.head;
while(cur != null){
count++;
cur = cur.next;
}
return count;
}
//6.任意位置插入,第一个数据节点为0号下标
//先找到index位置的前一个节点的地址
private Node searchIndex(int index) {
//先对index进行合法性检查
if (index < 0 || index > this.size()) {
throw new RuntimeException("index不合法!");
}
Node cur = this.head;
int count = 0;
while(count < index-1) {
count++;
cur = cur.next;
}
return cur;
}
public void addIndex(int index,int data) {
Node node = new Node(data);
this.searchIndex(index);
if (index == 0) {
this.addFirst(data);//index=0时相当于头插
return;
}
if (index == this.size()) {
this.addLast(data);//index=size时相当于尾插
return;
}
//先找到index位置的前一个节点的地址
Node cur = searchIndex(index);
//开始插入
node.next = cur.next;//先绑后面
cur.next = node;
}
//7.删除第一次出现的关键字key的节点
//找要删除的节点的前一个节点的位置prev
private Node searchPrev(int key) {
Node prev = this.head;
while (prev.next != null) {
if (prev.next.data == key) {
return prev;
}
prev = prev.next;
}
return null;
}
//删除key
public void remove(int key) {
//判断单链表是否为空,为空直接返回
if (this.head == null) {
return;
}
//判断key是否是头节点
if (this.head.data == key) {
this.head = this.head.next;
return;
}
//找到删除节点的前一个位置prev
Node prev = searchPrev(key);
if (prev == null) {
System.out.println("根本没有这个节点 ");
return;
}
Node del = prev.next;
prev.next = del.next;
}
//8.遍历单链表一遍,删除所有值为key的节点
public void allRemove(int key) {
Node prev = this.head;
Node cur = this.head.next;//代表要删除的节点
while (cur != null) {
if (cur.data == key) {
prev.next = cur.next;
cur = cur.next;
} else {
prev = cur;
cur = cur.next;
}
//最后处理头节点
if (this.head.data == key) {
this.head = this.head.next;
}
}
}
//9.clear清除:用来释放内存
public void clear() {
this.head = null;
}
//10.反转单链表
public Node reverseList() {
Node cur = this.head;
Node prev = null;
Node newHead = null;
while(cur != null) {
Node curNext = cur.next;
if(curNext == null){
newHead = cur;
}
cur.next = prev;
prev = cur;
cur = curNext;
}
return newHead;
}
//打印反转的单链表
public void display2(Node newHead) {
Node cur = newHead;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
/*也可以使用头插法进行反转,
先把头节点置为空,让下一个节点进行头插,遍历单链表*/
//11.找出中间节点,遍历一遍单链表(偶数取右)
public Node middleNode() {
Node fast = this.head;
Node slow = this.head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
//12.输入一个链表,输出该链表中倒数第k个节点。
public Node FindKthToTail(int k) {
if (k <= 0) {
System.out.println("k不合法");
return null;
}
if (this.head == null) {
return null;
}
Node fast = this.head;
Node slow = this.head;
//fast先走k-1步
while (k - 1 > 0) {
if (fast.next == null) {
System.out.println("k不合法");
return null;
}
fast = fast.next;
k--;
}
//fast,slow同时走
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
//13.以给定x为基准将链表分隔为两部分,所有小于x的结点排在大于或等于x的结点之前
/*1.两个线段的开始还有结束 bs be as ae =null
*2.定义一个cur遍历原来的单链表
* 3.如果cur.data<x 放到第一个线段,如果相反,放到第二个(尾插法)
* 4.当cur为空的时候,原来的单链表就遍历完了
* 注意:第一个段没有数据,返回as;be和as进行拼接,be.next = as.next;
* */
public Node partition(int x) {
Node bs = null;
Node be = null;
Node as = null;
Node ae = null;
Node cur = this.head;
while (cur != null) {
if (cur.data < x) {
//第一次插入
if (bs == null) {
bs = cur;
be = cur;
} else {
be.next = cur;
be = be.next;
}
}
else {
//第一次插入
if (as == null) {
as = cur;
ae = cur;
} else {
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next;
}
//判断bs是否为空
if (bs == null) {
return as;
}
be.next = as;
//ae是否为空,不是的话置为null
if (ae != null) {
ae.next = null;
}
return bs;
}
//14.在一个排序的链表中存在重复的结点,删除重复的结点,重复的结点不保留
/*1.定义一个虚拟节点
* */
public Node deleteDuplication() {
Node cur = this.head;
Node newHead = new Node(-1);
Node tmp = newHead;
while(cur != null) {
if (cur.next != null && cur.data == cur.next.data) {
while (cur.next != null && cur.data == cur.next.data){
cur = cur.next;
}
cur = cur.next;//再走一步
}else{
tmp.next = cur;
tmp = tmp.next;
cur = cur.next;
}
}
tmp.next = null;
return newHead.next;
}
//15.链表的回文结构
/*找到单链表的中间节点;反转单链表;一个从头走一个从尾走
* */
public boolean chkPalindrome() {
//单链表为空
if (this.head == null) {
return false;
}
//只有头节点自己,必然是回文结构
if (this.head.next == null) {
return false;
}
//1.找到单链表的中间节点
Node fast = this.head;
Node slow = this.head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//2.反转单链表的后半部分 slow在中间位置
Node cur = slow.next;
while(cur.next != null) {
Node curNext = cur.next;
cur.next = slow;
slow = cur;
cur = curNext;
}
//slow是最后一个节点了
//3.开始head从头走,slow从后走
while(slow == head) {
if (head.data != slow.data) {
return false;
}
if (this.head.next == slow){
return true;
}
head = head.next;
slow = slow.next;
}
return true;
}
//16.判断单链表是否有环
/*给定一个fast,一个slow,fast走两步,slow走一步,看能否相遇
* 为什么是两步?三步四步呢?
* 三步四步比两步相遇速度慢,而且有可能出现不会相遇的情况。
* */
public boolean hasCycle() {
Node fast = this.head;
Node slow = this.head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow){
return true;
}
}
return false;
}
//17.返回链表开始入环的第一个节点,如果链表无环,则返回null
//slow从相遇点走,head从头走,两个的相遇点即是入口点
public Node detectCycle() {
Node fast = this.head;
Node slow = this.head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow){
slow = this.head;
while(slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return null;
}
}
java-单链表
最新推荐文章于 2024-06-12 23:40:32 发布