数据结构与算法——双向链表
1.单向链表的缺点分析:
- 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
- 单向链表不能自我删除,需要依靠辅助节点;而双向链表,则可以自我删除。
2.双向链表思路分析:
分析双向链表的遍历、添加、修改、删除的操作思路。
(1)遍历:
方法和单链表一样,只是可以向前,也可以向后查找
(2)添加:
默认添加到双向链表的最后
- 先找到双向链表的最后这个节点
- temp.next = newHeroNode
- newHeroNode.pre = temp;
(3)修改:
修改思路和原来的单向链表一样
(4)删除:
- 因为是双向链表,因此,我们可以实现自我删除某个节点
- 直接找到要删除的这个节点,比如temp
- temp.pre.next = temp.next
- temp.next.pre = temp.pre;
因为遍历和修改的方法几乎没有改动,所以可以看我前面写的单链表的那些操作方法和思路数据结构与算法——单链表
3.代码逻辑:
1.节点对象的创建,和单链表有所不同的是,需要新增加一个属性pre,用于指向当前节点的上一个节点对象
class HeroNode2 {
public int no;
public String name;
public String nickname;
public HeroNode2 next;// 指向下一个节点
public HeroNode2 pre;// 指向前一个结点
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode2 [name=" + name + ", no=" + no + ", nickname=" + nickname + "]";
}
}
2.双向链表的创建以及增删改查方法的书写,主要是增加和删除的代码变化较大,主要是因为考虑到双向的因素,需要将next域和pre域都要前后连接起来,才是实现真正的双向,而其它方法操作几乎无变化。
class DoubleLinkedList {
// 1.创建头节点对象
private HeroNode2 head = new HeroNode2(0, " ", " ");
// 2.get/set方法为了后续方法体中获取该头节点
public HeroNode2 getHead() {
return head;
}
public void setHead(HeroNode2 head) {
this.head = head;
}
// 增删改查的方法:
// 3.遍历链表
public void show() {
// 1.判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
}
HeroNode2 temp = head.next;
// 2.链表非空的情况下遍历链表
while (true) {
if (temp == null) {// 表明此时该节点已经到链表的最后位置
break;
}
System.out.println(temp);
temp = temp.next;
}
}
// 4.在链表末尾增加节点
// 思路:1.找到末尾节点2.将最后这个节点的next指向新的,新的节点的pre指向末尾的
public void addNode(HeroNode2 newHeroNode) {
HeroNode2 temp = head;
while (true) {
if (temp.next == null) {
break;
}
temp = temp.next;
}
temp.next = newHeroNode;
newHeroNode.pre = temp;
}
// 5.删除节点信息
// 思路:1.根据no确定要删除的节点2.遍历链表寻找节点
// 思路:3.找到该节点后,将其上一个节点的next指向他下一个结点的pre,并将其下一个节点的pre指向其上一个节点的next
public void deleteNode(int no) {
if (head.next == null) {
System.out.println("当前链表为空~");
}
HeroNode2 temp = head;
boolean isFlag = false;
while (true) {
if (temp.next == null) {
break;
}
if (temp.no == no) {
isFlag = true;
break;
}
temp = temp.next;
}
// 通过isFlag标志来判断是否找到要删除的节点
if (isFlag) {
temp.pre.next = temp.next;
if (temp.next != null) {
temp.next.pre = temp.pre;
}
} else {
System.out.println("没有找到该节点~");
}
}
// 6.更新节点信息
// 思路:1.通过no来寻找要更新的节点2.遍历链表3.找到后,更新传入的参数
public void updateNoe(HeroNode2 newHeroNode) {
if (head.next == null) {
System.out.println("链表为空");
}
HeroNode2 temp = head;
boolean isFlag = false;
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no == newHeroNode.no) {
isFlag = true;
break;
}
temp = temp.next;
}
if (isFlag) {
temp.next.name = newHeroNode.name;
temp.next.nickname = newHeroNode.nickname;
} else {
System.out.println("未找到该节点~");
}
}
}
3.主函数测试
public class DoubleLinkedListTest {
public static void main(String[] args) {
System.out.println("测试双向链表及其功能---------------------");
// 1.创建对象
HeroNode2 hero1 = new HeroNode2(1, "qaq", "aqa");
HeroNode2 hero2 = new HeroNode2(2, "wsw", "sws");
HeroNode2 hero3 = new HeroNode2(3, "ede", "ded");
HeroNode2 hero4 = new HeroNode2(4, "rfr", "frf");
HeroNode2 hero5 = new HeroNode2(5, "tgt", "gtg");
// 2.创建链表
DoubleLinkedList dll = new DoubleLinkedList();
// 3.功能调用
// (1)增加
dll.addNode(hero1);
dll.addNode(hero3);
dll.addNode(hero5);
dll.addNode(hero2);
dll.addNode(hero4);
System.out.println("双向链表: ");
dll.show();
//(2)更新
dll.updateNoe(new HeroNode2(3, "uju", "juj"));
System.out.println("更新后的双向链表:");
dll.show();
//(3)删除:
System.out.println("删除前的双向链表:");
dll.show();
dll.deleteNode(2);
System.out.println("删除后的双向链表:");
dll.show();
}
}
4.测试结果展示:
马上开始学习栈啦,冲冲冲,家人们~~~~