要实现单链表的反转,我们首先需要创建一个单链表并实现CRUD操作,因我之前已写过类似的文章,故不再赘述,在此附上链接
单链表反转的思路:
首先我们创建一个新的辅助链表并获取其头结点,我们通过两个指针next,cur;cur指针指向当前遍历到的结点。next指针指向当前遍历到的结点的下一个结点。我们每遍历一个新的结点,就把这个结点放到新的这个头结点的最前面的位置,如此叠进,就能获得一个新的反转的单链表,最后再把head的next指向辅助链表的头结点的下一个结点。
下列是代码实现,要点在于创建一个新的链表,接用头结点
package com.liu.linkedlist;
/**
* @author liuweixin
* @create 2021-09-07 15:28
*/
//腾讯面试题,实现单链表的反转
public class TencentLinkedList {
private Node2 head = new Node2("", 0);//头结点;
public static void main(String[] args) {
TencentLinkedList list = new TencentLinkedList();//创建一个链表
System.out.println("反转前");
list.addNode2(new Node2("a", 1));
list.addNode2(new Node2("b", 2));
list.addNode2(new Node2("c", 3));
list.addNode2(new Node2("d", 4));
list.addNode2(new Node2("e", 5));
list.show();
System.out.println("反转后");
list.reverse();
list.show();
}
/**
* 反转链表的数据
*/
public void reverse() {
if (head.next == null || head.next.next == null) {
System.out.println("该链表没有数据或只有一个结点");
return;
}
Node2 cur = head.next;//指向第一个数据
Node2 next = null;//指向cur的下一个结点,为了保存cur的下一个结点不被丢失
TencentLinkedList reverse = new TencentLinkedList();//创建一个辅助链表,借用头结点
Node2 reverseHead = reverse.getHead();//借用头结点
while (cur != null) {
next = cur.next;//保存cur的下一个结点
cur.next = reverseHead.next;//把辅助链表的下一个结点赋给当前结点的下一个结点,实现辅助链表的一个后递
reverseHead.next = cur;
cur = next;//cur回归原链表
}
//循环结束,交换完毕,此时需把原链表的头结点指向辅助链表的第一个数据,这就实现了反转
head.next = reverseHead.next;
}
/**
* 获取头结点
*
* @return 返回头结点
*/
public Node2 getHead() {
return this.head;
}
/**
* 获取链表的总数
*
* @return 返回链表的总数
*/
public int getCount() {
int count = 0;
if (head.next == null) {//链表为空返回0
return 0;
}
Node2 cur = head;//创建一个辅助结点
while (cur.next != null) {//当cur的下一个结点不等于空时,count++,记录总数
count++;
cur = cur.next;//向下递换
}
return count;
}
/**
* 添加结点
*
* @param Node2 要加入的结点
*/
//对结点的操作放到链表中实现
public void addNode2(Node2 Node2) {
if (head.next == null) {
//只有一个头结点,可以直接把数据加入到链表中
head.next = Node2;
} else {
Node2 cur = head.next;//借助辅助结点去寻找到插入位置的前一个结点
while (cur.next != null && cur.next.no < Node2.no) {//当cur.next.no>Node2.no时退出循环,此时已找到插入位置的前一个结点。
//通过循环获取到插入位置的前一个结点
cur = cur.next;//cur需要下移,才能找到合适的位置
}
if (cur.next == null) {//找到链表的最后仍然没有比插入结点的no值大的,直接添加到链表的最后
cur.next = Node2;
return;
}
//此时cur.next.no>Node2.no,即找到插入位置的前一个结点
Node2.next = cur.next;//实现结点的传递
cur.next = Node2;
}
}
/**
* 删除链表的结点
*
* @param no 结点数据的编号
*/
public void deleteNode2(int no) {
if (head.next == null) {
System.out.println("链表为空,无法删除");
} else {
Node2 cur = head.next;//借助辅助结点去寻找到插入位置的前一个结点
while (true) {
if (cur.next == null) {//找到最后还没有找到删除的位置,说明该链表没有对应结点
System.out.println("链表无该节点,无法删除");
return;
}
if (cur.next.no == no) {
//此时已找到删除位置的前一个结点。
if (cur.next.next != null) { //删除结点的下一个结点不为空
cur.next = cur.next.next;
} else {//删除结点的下一个结点为空
cur.next = null;
}
return;//删除完成,结束方法
}
cur = cur.next;
}
}
}
/**
* 更改结点信息
*
* @param Node2 要更改的结点
*/
public void update(Node2 Node2) {
if (head.next == null) {
System.out.println("链表为空,无法更改");
} else {
Node2 cur = head;//借助辅助结点去寻找到插入位置的前一个结点
while (true) {
if (cur.next == null) {
if (cur.no != Node2.no) {
//找到最后还没有找到更新的位置,说明该链表没有对应结点
System.out.println("链表无该节点,无法更新");
}
return;
}
if (cur.next.no == Node2.no) {
//找到要更新的结点的前一个结点
if (cur.next.next != null) { //更新结点的下一个结点不为空
Node2.next = cur.next.next;
cur.next = Node2;//结点的移接
} else {//更新的结点是最后一个结点
cur.next = Node2;
}
return;
}
cur = cur.next;
}
}
}
/**
* 遍历链表数据
*/
public void show() {
if (head.next == null) {
System.out.println("该链表无数据");
return;
}
Node2 cur = head.next;
while (cur != null) {//注意这里的指针变化,这里的指针指的是当前遍历的结点,而不是遍历结点的前一个结点,这里跟上面添加和删除的临时结点不同
System.out.println(cur);
cur = cur.next;
}
}
}
class Node2 {//定义一个结点对象,每一个对象就是一个结点
Node2 next;
String name;
int no;
public Node2(String name, int no) {
this.name = name;
this.no = no;
}
@Override
public String toString() {
return "Node2{" +
" name='" + name + '\'' +
", no=" + no +
'}';
}
}