数据结构与算法之双向链表
- 管理单链表的缺点分析:
- 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
- 单链表不能自我删除,需要靠辅助节点,而双向链表则可以自我删除
图解:
- 代码实现:
创建一个节点的类
/*
* 创建一个节点的类
*
* */
class HeroNode2{
public int no;
public String name;
public HeroNode2 next; //指向下一个节点 默认为null
public HeroNode2 pre; //指向上一个节点 默认为null
//构造器
public HeroNode2(int no,String name){
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "HeroNode2{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
双向链表类及其增删查改功能:
class DoubleLinkedList{
//初始化定义一个头节点
private HeroNode2 head = new HeroNode2(0,null);
//返回头节点
public HeroNode2 getHead(){
return head;
}
//遍历双向链表(与单链表一致)
public void showDoubleLinkedList(){
if (head.next == null ){
System.out.println("链表为空!");
return;
}
HeroNode2 temp = head.next;
while(true){
if (temp == null){
break;
}
System.out.println(temp);
temp = temp.next;
}
}
/*
* 添加数据到双向链表中
* */
public void add(HeroNode2 heroNode2){
//辅助节点
HeroNode2 temp = head;
//找到当前链表的尾部,将数据插入
while(true){
if (temp.next == null){
break;
}
temp = temp.next;
}
//形成双向链表
temp.next = heroNode2;
heroNode2.pre = temp;
}
/*
* 删除一个基节点信息
*
* */
public void del(int no) {
if (head.next == null ){
System.out.println("链表为空,无法删除!");
return;
}
HeroNode2 temp = head.next; //辅助变量
boolean flag = true; //标志是否找到待删除的节点
while (true){
if (temp == null){
break;
}
if (temp.no == no){
flag = true;
break;
}
temp = temp.next;
}
/*
* 找到待删除节点
* */
if (flag){
temp.pre.next = temp.next;
if (temp.next != null) {
//否则如果待删除节点是最后一个节点则会造成空指针异常
temp.next.pre = temp.pre;
}
}else {
System.out.printf("未找到编号为%d的节点信息,无法删除",no);
}
}
/*
* 查找一个节点的信息
*
**/
public void searchNode(int no){
if (head.next == null ){
System.out.println("链表为空!");
return ;
}
HeroNode2 temp = head;
boolean flag = false;
while(true){
if (temp.next == null){
break;
}
if (temp.no == no){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
System.out.println(temp);
}else{
System.out.printf("未找到编号为%d的节点信息",no);
}
}
/*
* 修改一个节点的信息
* */
public void update(HeroNode2 newHeroNode){
//判断是否为空
if (head.next == null){
System.out.println("链表为空!");
return;
}
//找到需要修改的节点
HeroNode2 temp = head.next;
boolean flag = false;
while (true){
if (temp.next == null){
break;
}if (temp.no == newHeroNode.no){
flag = true;
break;
}
temp = temp.next; //后移
}
if (flag){
temp.name = newHeroNode.name;
}else {
System.out.printf("未找到编号为%d的信息,无法修改",newHeroNode.no);
}
}
/*
* 通过序号添加节点信息
*
* */
public void addByOrder(HeroNode2 heroNode2){
HeroNode2 temp = head.next;
while (true){
//判断双向链表是否为空
if (head.next == null){
head.next = heroNode2;
heroNode2.pre = head;
heroNode2.next = null;
break;
}
if (temp.no == heroNode2.no ){
System.out.printf("已经存在编号为%d的节点信息",heroNode2.no);
return;
}
if (temp.no > heroNode2.no){
//插入到temp的前面
temp.pre.next = heroNode2;
heroNode2.pre = temp.pre;
heroNode2.next = temp;
temp.pre = heroNode2;
break;
}
if (temp.next == null){
temp.next = heroNode2;
heroNode2.pre = temp;
heroNode2.next = null;
break;
}
temp = temp.next;
}
}
}
特别注意:
注意空指针异常,每个节点对应的next和pre指针必须指定到位。