个人感悟:在单向链表的CRUD中需要更加注意辅助指针的指向,比如在删除节点时,无法直接删除辅助指针指向的节点,因为无法找到前一个节点,并让其指向当前节点的后一个节点。此时的解决方法就是永远让你的辅助指针在你想要比较的节点的前面一个节点,这样就可以轻松让前一个节点指向后一个节点了。
而在双向链表中则没有这种担忧,直接干就完了。
(最后更新时间 2020/8/22 2:24)
以下为带头节点的链表(双向链表处的代码更加凝练)
单向链表的增删改查操作
package 单链表.基础;
import java.util.Stack;
public class SingleLinkedListDemo {
public static void main(String[] args) {
//进行测试
//先创建节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(3, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(5, "吴用", "智多星");
HeroNode hero4 = new HeroNode(7, "林冲", "豹子头");
HeroNode hero5 = new HeroNode(2, "宋江2", "及时雨2");
HeroNode hero6 = new HeroNode(4, "卢俊义2", "玉麒麟2");
HeroNode hero7 = new HeroNode(6, "吴用2", "智多星2");
HeroNode hero8 = new HeroNode(8, "林冲2", "豹子头2");
//创建要给链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
SingleLinkedList singleLinkedList2 = new SingleLinkedList();
//加入
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero2);
singleLinkedList.addByOrder(hero3);
singleLinkedList2.addByOrder(hero5);
singleLinkedList2.addByOrder(hero6);
singleLinkedList2.addByOrder(hero8);
singleLinkedList2.addByOrder(hero7);
singleLinkedList.update(4,"被修改");
// singleLinkedList.del(1);
// System.out.println(getLength(singleLinkedList.head));
// try {
// System.out.println(findLastIndexNode(1,singleLinkedList.head));
// }catch (Exception e){
// System.out.println(e.getMessage());
// }
// reversePrint(singleLinkedList.head);
mergeLinkedList(singleLinkedList,singleLinkedList2.head);
singleLinkedList.list();
// singleLinkedList2.list();
// reversetList(singleLinkedList.head);
// singleLinkedList.list();
}
//统计链表内节点的个数
public static int getLength(HeroNode head){
if (head.next == null){
return 0;
}
int length = 1;
HeroNode cur = head.next;
while (true){
if (cur.next == null){
break;
}
length++;
cur = cur.next;
}
return length;
}
//查找倒数第k个节点【新浪面试题】
public static HeroNode findLastIndexNode(int lastIndex, HeroNode head){
int length = getLength(head);
if (lastIndex > length || lastIndex < 1){
throw new RuntimeException("超出范围");
}
int index = length - lastIndex + 1;//正数第几个
HeroNode temp = head;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp;
}
//单链表的反转【腾讯面试题】
public static void reversetList(HeroNode head){
if (head.next == null || head.next.next == null){
return;
}
HeroNode temp = head.next;
HeroNode temp2 = null;
HeroNode next = null;
HeroNode reverseNode = new HeroNode(0,null,null);
/*while (true){//自己想法
if (temp.next == null){
temp.next = reverseNode.next;
reverseNode.next = temp;
head.next = reverseNode.next;
break;
}
temp2 = temp;
temp = temp.next;
temp2.next = reverseNode.next;
reverseNode.next = temp2;
}*/
//老师给的方法
while (temp != null){
next = temp.next;
temp.next = reverseNode.next;
reverseNode.next = temp;
temp = next;
}
head.next = reverseNode.next;
return;
}
//逆序打印单链表【百度面试题】
public static void reversePrint(HeroNode head){
if (head.next == null){
return;
}
HeroNode temp = head.next;
Stack<HeroNode> stack = new Stack<>();
while (temp != null) {
stack.push(temp);
temp = temp.next;
}
while (stack.size()>0){
System.out.println(stack.pop());
}
}
//合并两个有序链表
public static void mergeLinkedList(SingleLinkedList singleLinkedList, HeroNode head){
if (head.next == null) {
return;
}
HeroNode temp = head.next;
HeroNode next = null;
while (true) {
if (temp.next == null) {
singleLinkedList.addByOrder(temp);
return;
}
next = temp.next;
singleLinkedList.addByOrder(temp);
temp = next;
}
}
}
class SingleLinkedList{
HeroNode head = new HeroNode(0,null,null);
//添加人物
public void add(HeroNode heroNode){
HeroNode temp = head;
while (true) {
if (temp.next == null) {
break;
}
temp = temp.next;
}
temp.next = heroNode;
}
//顺序添加人物
public void addByOrder(HeroNode heroNode){
HeroNode temp = head;
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no > heroNode.no){
break;
}
temp = temp.next;
}
heroNode.next = temp.next;
temp.next = heroNode;
}
//改变指定节点信息
public void update(int no, String newName){
if (head.next == null){
System.out.println("链表为空");
}
HeroNode temp = head.next;
while (true){
if (temp.next == null){
if (temp.no == no){
temp.name = newName;
}else {
System.out.println("没找到");
}
break;
}
if (temp.no == no){
temp.name = newName;
break;
}
temp = temp.next;
}
}
//删除指定节点
public void del(int no){
if (head.next == null){
System.out.println("链表为空");
}
HeroNode temp = head;
while (true) {
if (temp.next == null){
System.out.println("未找到指定数据");
break;
}
//判断下一个是否一样,一样删除
if (temp.next.no == no){
temp.next = temp.next.next;
break;
}
//不一样,下一个
temp = temp.next;
}
}
//打印全部链表
public void list(){
if (head.next == null) {
System.out.println("链表为空");
}
HeroNode temp = head.next;
while (true) {
if (temp == null){
break;
}
System.out.println(temp);
temp = temp.next;
}
}
}
class HeroNode{
public int no;
public String name;
public String nickName;
public HeroNode next;
public HeroNode(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
双向链表的增删改查操作

package 双向链表;
public class DoubleLinkedListDemo {
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, "林冲", "豹子头");
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
// doubleLinkedList.add(hero1);
// doubleLinkedList.add(hero4);
// doubleLinkedList.add(hero2);
// doubleLinkedList.add(hero3);
doubleLinkedList.addByOrder(hero1);
doubleLinkedList.addByOrder(hero4);
doubleLinkedList.addByOrder(hero3);
doubleLinkedList.addByOrder(hero2);
// doubleLinkedList.del(3);
// doubleLinkedList.update(new HeroNode(4,"修改","修改"));
doubleLinkedList.list();
}
}
class DoubleLinkedList {
private HeroNode head = new HeroNode(0, null, null);
public HeroNode getHead() {
return head;
}
//遍历双向链表
public void list(){
if (head.next == null){
System.out.println("链表为空");
return;
}
HeroNode temp = head.next;
while (temp != null){
System.out.println(temp);
temp = temp.next;
}
}
//添加节点到最后
public void add(HeroNode heroNode){
HeroNode temp = head;
while (temp.next != null){
temp = temp.next;
}
temp.next = heroNode;
heroNode.prev = temp;
}
//按照编号大小顺序添加
public void addByOrder(HeroNode heroNode){
HeroNode temp = head;
while (temp.next != null){
if (temp.next.no > heroNode.no){
heroNode.next = temp.next;
heroNode.prev = temp;
temp.next.prev = heroNode;
temp.next = heroNode;
return;
}else if (temp.next.no == heroNode.no){
System.out.println("已有该编号的节点");
return;
}
temp = temp.next;
}
// this.add(heroNode);//感觉效率不高,还是算了
temp.next = heroNode;
heroNode.prev = temp;
}
//修改节点内容
public void update(HeroNode newNeroNode){
if (head.next == null){
System.out.println("链表为空");
return;
}
HeroNode temp = head.next;
boolean flag = false;
while (temp != null){
if (temp.no == newNeroNode.no){
flag = true;
temp.name = newNeroNode.name;
temp.nickName = newNeroNode.nickName;
return;
}
temp = temp.next;
}
if (flag == false){
System.out.printf("没找到编号为%d的节点\n",newNeroNode.no);
}
}
//删除节点
public void del(int no){
if (head.next == null){
System.out.println("链表已空");
return;
}
HeroNode temp = head.next;
boolean flag = false;
while (temp != null){
if (temp.no == no){
flag = true;
break;
}
temp = temp.next;
}
if (flag == false){
System.out.println("未找到该节点");
}else {
temp.prev.next = temp.next;
if (temp.next != null) temp.next.prev = temp.prev;//最后一个要特殊处理!!不然空指针异常
}
}
}
class HeroNode{
public int no;
public String name;
public String nickName;
public HeroNode next;
public HeroNode prev;
public HeroNode(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
本文深入探讨了单向链表和双向链表的创建、读取、更新和删除(CRUD)操作,重点讲解了在单向链表中辅助指针的正确使用方法,以及双向链表中更为简洁的实现方式。通过具体代码示例,对比了两种链表类型在操作上的差异。
788

被折叠的 条评论
为什么被折叠?



