常用链表的操作:
单链表反转 * 链表中环的检测 * 两个有序的链表合并 * 删除链表倒数第 n 个结点 * 求链表的中间结点
public class LinkedNode {
public Node<Integer> getHeader() {
return header;
}
private Node<Integer> header;
/**
* 添加节点
*
* @param val
*/
public void addNode(int val) {
if (null == header) {
//一开始是没有后面的节点的
header = new Node<Integer>(val, null);
return;
}
//每次添加的时候总是往最前面添加,单链表的结构就是不论从前往后还是从后往前都是添加到第一个了,也就是只有第一个才能开始查找起来
header = new Node<Integer>(val, header);
}
/**
* 这是先进后出的一种添加链表的方式
* @param val
* @param header
* @return
*/
public Node<Integer> addNameNode(int val, Node<Integer> header) {
if (null == header) {
header = new Node<>(val, null);
return header;
}
header = new Node<>(val, header);
return header;
}
public void addNode(int val, Node<Integer> header){
if (null == header) {
header = new Node<>(val, null);
}
Node<Integer> newNode=new Node<>(val,null);
Node<Integer> p=header;
while(true){
if(null==p.getNext()){
p.setNext(newNode);
break;
}
p=p.next;
}
}
/**
* 单链表反转
*
* @param header
* @return
*/
public Node<Integer> reverseLink(Node<Integer> header) {
if (null == header || null == header.getNext()) {
return header;
}
Node<Integer> cur = header.getNext();
Node<Integer> pre = header;
while (null != cur) {
//先把下一个节点临时存起来
Node<Integer> next = cur.getNext();
//这一行才是核心,就是把next的指针从下一个 换成上一个
cur.setNext(pre);
//把上一个指针挪到当前的,准备下一个
pre = cur;
//把当前的指针挪到下一个,准备下一次呼唤
cur = next;
}
//这个时候需要把一开始的头节点置空,不然就会出现循环引用的情况,因为改变之后的倒数第二个节点的next和原来的header形成相互引用
header.setNext(null);
return pre;
}
/**
* 核心就是每次从最后一个加到第一个,然后不断地删掉多加的,和之前的循环不太一样的
*
* @param header 每次递归获得的header都是一个节点的引用
* @return
*/
public Node<Integer> reverseLinked2(Node<Integer> header) {
if (null == header || null == header.getNext()) {
//这一步是最核心的,因为新的节点起点从这里开始
return header;
}
//最后一个节点调用的时候最先返回的是最后一个节点,这个node引用是从之前的最后一个节点开始记录的,不断的添加新的节点每次添加一个header,而header执行到最后的时候其实是之前的第一个个节点
Node<Integer> Node = reverseLinked2(header.getNext());
//从倒数第二次递归开始获得的值,也就是倒数第二个节点要想给最后一个节点后面加值,就只能这样设置,最后一个节点的next设置为倒数第二个节点
header.getNext().setNext(header);
//这样的话,每次都是添加的header这个引用的这样一个几点
header.setNext(null);
return Node;
}
public void iterate(Node<Integer> header) {
if (null == header) {
return;
}
Node<Integer> next = header;
while (null != next) {
System.out.print(" " + next.getVal());
next = next.getNext();
}
}
/**
* 链表中环的检测
*
* @param header
* @return
*/
public boolean hasLoop(Node<Integer> header) {
Node<Integer> slowPoint = header;
Node<Integer> fastPoint = header.getNext();
while (null != fastPoint && null != fastPoint.getNext()) {
slowPoint = slowPoint.getNext();
fastPoint = fastPoint.getNext().getNext();
if (null == fastPoint) {
return false;
}
if (slowPoint.equals(fastPoint)) {
return true;
}
}
return false;
}
/**
* 有序链表的合并
*
* @return
*/
public Node<Integer> mergeLinked(Node<Integer> n1, Node<Integer> n2) {
Node<Integer> guard = new Node<>(-1, null);
//定义两个指针记录两个链表的走的位置
Node<Integer> p1 = n1;
Node<Integer> p2 = n2;
//定义一个指针定义当前的位置
Node<Integer> curNode = guard;
while (null != p1 && null != p2) {
if (p1.getVal() > p2.getVal()) {
curNode.setNext(p1);
p1 = p1.getNext();
} else {
curNode.setNext(p2);
p2 = p2.getNext();
}
curNode = curNode.getNext();
}
return guard.getNext();
}
/**
* 递归的就是从最后一个的返回值出发,然后进行,递归就是一定要有返回值,每次都去操作这个返回值
* @param n1
* @param n2
* @return
*/
public Node<Integer> mergeList(Node<Integer> n1, Node<Integer> n2){
if(null==n1){
return n2;
}
if(null==n2){
return n1;
}
if(n1.getVal()>n2.getVal()){
n1.next=mergeList(n1.getNext(),n2);
return n1;
}else{
n2.next=mergeList(n1,n2.next);
return n2;
}
}
/**
* 删除倒数第n个节点
* @param n
* @param num
* @return
*/
public Node<Integer> removeLastNode(Node<Integer> n,int num){
//思路就是1、首先找到倒数第n个节点,有两个办法,一个是直接把当前的单链表反转过来,顺着数到第n个
//思路2 西安遍历到最后一个,然后从最后一个开始
Node<Integer> pre = getIntegerNode(n);
Node p=pre;
int count=0;
while(true){
count++;
if(count==num){
p.next=p.next.next;
break;
}
p=p.next;
}
Node<Integer> integerNode = getIntegerNode(pre);
return integerNode;
}
private Node<Integer> getIntegerNode(Node<Integer> n) {
Node<Integer> pre=null;
Node<Integer> cur=n;
while(null!=cur){
Node temp=cur.getNext();
cur.setNext(pre);
pre=cur;
cur=temp;
}
return pre;
}
/**
* part就相当于一个指针一样的
* @param n1
* @param num
* @return
*/
Node<Integer> removeList(Node<Integer> n1,int num){
Node<Integer> header=new Node<>(-1,null);
Node<Integer> part=n1;
Node<Integer> all=n1;
header.next=n1;
while(null!=part&&num>=0){
part=part.next;
num--;
}
while(null!=part){
part=part.next;
all=all.next;
}
all.next=all.next.next;
return header.next;
}
Node<Integer> findMiddleNode(Node<Integer> header){
if(null==header){
return header;
}
Node<Integer> fast=header;
Node<Integer> slow=header;
while(null!=fast){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
}
接下来需要用到的就是写一个链表的实体类
class Node<T> {
/**
* 存放数据的地方
*/
T val;
/**
* 存放引用的地方(C语言中的指针,意思差不多)
*/
Node<T> next;
public Node(T val, Node<T> next) {
this.val = val;
this.next = next;
}
public T getVal() {
return val;
}
public Node<T> getNext() {
return next;
}
public void setVal(T val) {
this.val = val;
}
public void setNext(Node<T> next) {
this.next = next;
}
}
至此 所有的Java代码已经完成