定义一个节点对象
// 定义节点,每个heroNode对象都是一个节点
class HeroNode {
int no;
String name;
String nickName;
HeroNode next;
public HeroNode(int no, String name, String nickName) {
this.no = no;
this.nickName = nickName;
this.name = name;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
定义节点的操作对象,有链表的创建,顺序创建,修改,删除和遍历,新浪,百度,腾讯面试题,还有一个获取单链表中节点的个数。
class SingleLinkedList {
private HeroNode head = new HeroNode(0, "", "");
// 获取链表节点的个数
/**
* 获取链表中的节点个数
* @param head 头节点
* @return
*/
public static int getLinkedLength(HeroNode head){
HeroNode temp = head;
int count = 0;
while(temp.next != null){
count++;
temp = temp.next;
}
return count;
}
/**
* 单链表的逆序打印,不损坏链表的结构(百度面试题)
* 分析:用栈的数据结构完成(stack)
* @param head
*/
public static void reversePrint(HeroNode head){
if(head.next == null){
return ;
}
Stack<HeroNode> stack = new Stack<>();
HeroNode curNode = head.next;
while(curNode != null){
stack.push(curNode);
curNode = curNode.next;
}
while(stack.size() > 0){
System.out.println(stack.pop());
}
}
/**
* 链表的反转(腾讯面试题)
*/
public static void reverseLinked(HeroNode head){
HeroNode curNode = head.next;// 当前节点
HeroNode next = null;// 当前节点的下一个节点
HeroNode reverseHead = new HeroNode(0,"","");// 创建一个新链表,用于存储反转后的数据
while(curNode != null){
next = curNode.next;// 当前节点的下一个节点
curNode.next = reverseHead.next;// 当前节点的下一个节点指向新链表的最前端
reverseHead.next = curNode; // curNode连接到reverseHead链表上
curNode = next;
}
head.next = reverseHead.next;
}
// 寻找单链表中,倒数第k个节点
/**
* 新浪面试题 解法1
* @param head 头结点
* @param k 倒数第K个节点
* @return
*/
public static HeroNode findLastIndexNode(HeroNode head,int k){
HeroNode frontNode = head.next;
HeroNode secondNode = head.next;
int linkedLength = getLinkedLength(head);
if(k > linkedLength){
System.out.println("链表中没有倒数第"+k+"个节点");
return null;
}
for(int i=0;i<k;i++){
secondNode = secondNode.next;
}
while(secondNode != null){
frontNode = frontNode.next;
secondNode = secondNode.next;
}
return frontNode;
}
// 寻找单链表中,倒数第k个节点
/**
* 新浪面试题 解法2
* @param head 头结点
* @param k 倒数第K个节点
* @return
*/
public static HeroNode findLastIndexNode2(HeroNode head,int k){
HeroNode temp = head.next;
int linkedLength = getLinkedLength(head);
if(k <= 0 || k > linkedLength){
return null;
}
for(int i=0;i<linkedLength-k;i++){
temp = temp.next;
}
return temp;
}
// 添加节点
public void add(HeroNode heroNode) {
HeroNode temp = head;
while (true) {
if (temp.next == null) {
temp.next = heroNode;
break;
}
temp = temp.next;
}
}
// 删除链表
public void del(int no){
HeroNode temp = head; // 要删除节点的前一个节点
boolean flag = false;
while(true){
if(temp.next == null){
break;
}
if(temp.next.no == no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.next = temp.next.next;// 要删除节点的前一个节点的指针指向要删除节点的后一个节点
}else{
System.out.println("删除失败,没有该节点:"+no);
}
}
// 更新链表中的节点
public void update(HeroNode newHeroNode){
HeroNode temp = head.next;
boolean flag = false;
while(true){
if(temp == null){
System.out.println("链表为空...");
break;
}
// 找到了相对应的节点
if(temp.no == newHeroNode.no){
flag = true;
break;
}
temp = temp.next;
}
if(!flag){
System.out.println("链表中没有此节点");
}else{
temp.name = newHeroNode.name;
temp.nickName = newHeroNode.nickName;
}
}
// 顺序添加节点
public void addByOrder(HeroNode heroNode) {
HeroNode temp = head;// temp为要插入节点的前一个节点
boolean flag = false;
while(true){
if(temp.next == null){
break;
}
if(temp.next.no > heroNode.no){ // 要插入的位置找到了,就在temp后面插入
break;
}else if(temp.next.no == heroNode.no){
flag = true;
}
temp = temp.next;
}
if(flag){
System.out.println("准备插入的节点已存在:"+heroNode.no);
}else{
// 插入到链表中
heroNode.next = temp.next;// temp为要插入节点的前一个节点
temp.next = heroNode;
}
}
// 遍历链表
public void list() {
HeroNode temp = head.next;
while (true) {
if (temp == null) {
break;
}
System.out.println(temp);
temp = temp.next;
}
}
}
测试
/**
* @author AN
* @create 2020-08-06 8:43
*/
public class SingleLinkedListDemo {
public static void main(String[] args) {
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");
SingleLinkedList singleLinkedList = new SingleLinkedList();
// 顺序一个一个的加入
// singleLinkedList.add(hero1);
// singleLinkedList.add(hero4);
// singleLinkedList.add(hero2);
// singleLinkedList.add(hero3);
// 按照no的顺序加入
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero2);
singleLinkedList.addByOrder(hero3);
// 遍历节点
singleLinkedList.list();
singleLinkedList.reverseLinked(singleLinkedList.getHeadNode());
System.out.println("链表反转之后");
singleLinkedList.list();
System.out.println("链表逆序打印");
singleLinkedList.reversePrint(singleLinkedList.getHeadNode());
// HeroNode newHeroNode = new HeroNode(4, "林冲1", "豹子头123");
// // 更新链表中的一个节点
// singleLinkedList.update(newHeroNode);
//
// System.out.println("修改后的链表...");
// // 遍历链表
// singleLinkedList.list();
//
// // 删除节点
// singleLinkedList.del(4);
// singleLinkedList.del(1);
// System.out.println("删除后的链表...");
// // 打印节点
// singleLinkedList.list();
//
// System.out.println("倒数第K个节点");
// HeroNode lastIndexNode = singleLinkedList.findLastIndexNode2(singleLinkedList.getHeadNode(), 2);
// System.out.println(lastIndexNode);
// System.out.println("链表的节点个数:"+singleLinkedList.getLinkedLength(singleLinkedList.getHeadNode()));
}
}
测试结果
还有一些测试数据没有列出来,可以一个个方法测试一下。