文章目录
1.统计单链表中有效节点的个数
java
/**
* 获取单链表中有效节点数量,除去头节点外的节点
*
* @return 返回节点个数
*/
public int getLength() {
if (isEmpty()) { // 如果为空,则返回0
return 0;
} else { // 如果不为空,需要遍历
int num = 0;
HeroNode tempNode = this.headNode;
do {
tempNode = tempNode.getNext();
num++;
} while (tempNode.getNext() != null);
return num;
}
}
2.查找单链表中倒数第k个节点【新浪面试题】
java
/**
* 查找单链表中倒数第k个节点【新浪面试题】
* 1. 先计算总节点个数
* 2. 倒数是第k个节点,那正数是第几个?length-(k-1)==> length-k+1
*
* @param k 倒数第k个节点
* @return 返回查找的节点
*/
public HeroNode getNodeByTailK(int k) {
int Length = this.getLength();
int index = Length - k + 1; // 正数的下标
// 如果单链表长度为0或者k值大于链表长度,则返回null
if (Length == 0 || k > Length) {
return null;
} else { // 返回第index个节点
HeroNode tempNode = this.headNode;
for (int i = 1; i <= index; i++) {
tempNode = tempNode.getNext();
}
return tempNode;
}
}
3.单链表的反转【腾讯面试题】

使用"头插法",每次将新节点插入链表的第一个有效节点位置,旧链表从头开始遍历即可,这样新链表中元素就形成了反转。
java
/**
* 单链表的反转【腾讯面试题】
* 将链表中的元素反转
*
* @return 返回新链表
*/
public SingleLinkedList_Heroes reverse() {
SingleLinkedList_Heroes reverse_linked_list = new SingleLinkedList_Heroes(); // 默认只有一个头节点
// 1.先判断链表是否为空,如果为空,直接返回头节点即可
if (!this.isEmpty()) {
// 2.如果不为空,从原链表头部遍历,将元素链接到新链表头部与第一个节点直接,形成反转
HeroNode tempNode_old = this.getHeadNode().getNext(); // 原链表的第一个有效节点
HeroNode tempNode_head = reverse_linked_list.getHeadNode(); // 新链表头节点
HeroNode tempNode_no1 = tempNode_head.getNext(); // 新链表第一个有效节点,一开始为null
while (tempNode_old != null) {
HeroNode tempNode = new HeroNode(tempNode_old); // 待插入的节点数据;这里一定要创建新节点,不能引用地址
tempNode.setNext(tempNode_no1); // 该节点作为新链表中第一个有效节点
tempNode_head.setNext(tempNode); // 将新链表头节点指向该节点
tempNode_no1 = tempNode_head.getNext(); // 更新新列表第一个有效节点
tempNode_old = tempNode_old.getNext(); // 继续遍历原链表
}
}
return reverse_linked_list;
}
4.将单链表逆向打印【百度面试题】
方法一:先将链表元素反转再打印;
方法二:使用"栈"数据结构,将链表元素依次压入栈中,再利用栈的先入后出的特性将元素取出,形成逆序打印;
下面代码使用方法二:
java
/**
* 使用栈逆序打印链表元素
*/
public void reversePrint() {
if (this.isEmpty()) { // 如果链表为空
System.out.println("单链表为空!");
} else {
Stack<HeroNode> stack = new Stack<>(); // 初始化栈
HeroNode tempNode = this.getHeadNode().getNext();
// 将链表元素入栈
while (tempNode != null) {
stack.push(tempNode);
tempNode = tempNode.getNext();
}
// 将所有元素出栈,形成逆序打印
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
}
5.将两个有序单链表合成一个有序单链表
java
/**
* 静态方法,合并两个有序链表,返回新链表对象
*
* @param list1 有序链表1
* @param list2 有序链表2
* @return 合并之后有序链表
*/
public static SingleLinkedList_Heroes mergeTwoList(SingleLinkedList_Heroes list1, SingleLinkedList_Heroes list2) {
// 1.判断两个链表是否为空;list1为空返回list2;list2为空返回list1;
if (list1.isEmpty()) {
return list2;
} else if (list2.isEmpty()) {
return list1;
} else {
// 2.两者都不为空时,创建新链表,用两个指针指向list1和list2,从有效节点开始顺序遍历,直至两个指针指向null;
SingleLinkedList_Heroes newList = new SingleLinkedList_Heroes();
HeroNode tempNode1 = list1.getHeadNode().getNext(); // 指针一指向list1的第一个有效节点
HeroNode tempNode2 = list2.getHeadNode().getNext(); // 指针二指向list2的第一个有效节点
while (tempNode1 != null && tempNode2 != null) { // 遍历条件:两个指针均不为null时才遍历
// 3.每次都进行比较,按照升序方式加入新链表;这里按照no编号继续比较;需要考虑相等的情况
if (tempNode1.getNo() <= tempNode2.getNo()) { // 小数据节点排在前面
newList.addHero(new HeroNode(tempNode1));
newList.addHero(new HeroNode(tempNode2));
} else {
newList.addHero(new HeroNode(tempNode2));
newList.addHero(new HeroNode(tempNode1));
}
tempNode1 = tempNode1.getNext();
tempNode2 = tempNode2.getNext();
}
// 4.循环结束后,一定有其中一个链表还有剩余节点,**单独把剩下的节点循环拷贝加入新链表**。
// 4.1 考虑两个链表的节点数量
int num1 = list1.getLength();
int num2 = list2.getLength();
if (num1 == num2) { // 4.2 如果两个链表节点数量相同表示节点已遍历完毕,直接返回即可
return newList;
} else if (num1 > num2) { // 4.3 如果list1节点数量多于list2,表示list1中有剩余节点没有遍历,剩余节点数量:num1-num2;然后按照顺序插入
int leave = num1 - num2;
while (leave != 0) {
// 4.4 先获取尾部第leave个节点,注意需要new新节点
HeroNode heroNode = new HeroNode(list1.getNodeByTailK(leave));
// 4.5 再按照no值插入新链表中
newList.addHeroByOrder(heroNode);
leave--;
}
return newList;
} else { //list2节点数量多于list1的情况,跟上面相同
int leave = num2 - num1;
while (leave != 0) {
// 4.4 先获取尾部第leave个节点,注意需要new新节点
HeroNode heroNode = new HeroNode(list2.getNodeByTailK(leave));
// 4.5 再按照no值插入新链表中
newList.addHeroByOrder(heroNode);
leave--;
}
return newList;
}
} ```