一、简介
双向链表在查询数据时有一个优势,就是在查询数据时并不像单向链表那样要从头到尾的查,而是可以在链表的某一中间的某一个数据向前或向后查询其它数据,使查询时间进一步缩短了那么一点点。
二、双向链表的示例代码如下:
/**
* 包名:linkedlist
* 文件名:DoubleLinkedListDemo.java
*
* 功能:双链表数据结构的增删改查
*
* 作者:冰雪青松
* 邮箱:946585434@qq.com
* 日期:2022.10.13
*
**/
package linkedlist;
import java.util.*;
/**
* 一、主类,即入口类,
*
* 说明:是对双向链表数据结构的操作,是次要的类
*
**/
public class DoubleLinkedListDemo {
public static void main(String[] args) {
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
//########## [ 对双向链表的增删改查的操作 ]######################
//------------------------------------------------------------------------------------------------------------------------------
// 1.遍历二维数组添加数据进双向链表 begin
//建立数据的二维数组
String[][] nameArr = {
{"宋江", "卢俊义", "吴用", "林冲", "公孙胜", "关胜", "秦明", "公孙胜", "呼延灼", "花荣"},
{"及时雨", "玉麒麟", "智多星", "豹子头", "入云龙", "大刀", "霹雳火", "入云龙", "双鞭", "小李广"}
};
//编号,排序依据此偏号,可修改编号查看排序情况
int[] noArr = {1, 9, 2, 5, 8, 10, 4, 3, 7, 6};
//true 不排序;false 排序
boolean tag = false;
//遍历二维数组添加节点进链表
if(tag){
//按输入顺序进链表
for(int i = 0; i < nameArr[0].length; i++){
doubleLinkedList.add(new DHeroNode(noArr[i] , nameArr[0][i], nameArr[1][i]));
}
}else{
//按排序进链表
for(int i = 0; i < nameArr[0].length; i++){
doubleLinkedList.addByOrder(new DHeroNode(noArr[i], nameArr[0][i], nameArr[1][i]));
}
}
System.out.println("--------------------------------------");
System.out.println("一、双向链表添加数据:\n");
//遍历显示
doubleLinkedList.list();
System.out.println("--------------------------------------");
// 1.遍历二维数组添加数据进双向链表 end.
//------------------------------------------------------------------------------------------------------------------------------
// 2.修改双向链表 begin
int upNo1 = 2;
String upName1 = "孙悟空";
String upNick1 = "齐天大圣";
int upNo2 = 6;
String upName2 = "猪八戒";
String upNick2 = "花心大萝卜";
System.out.printf("\n二、准备修改的内容:\n\n编号:%d,姓名:%s,绰号:%s", upNo1, upName1, upNick1);
System.out.printf("\n编号:%d,姓名:%s,绰号:%s", upNo2, upName2, upNick2);
System.out.println("\n\n修改后的数据:\n");
doubleLinkedList.update(new DHeroNode(upNo1, upName1, upNick1));
doubleLinkedList.update(new DHeroNode(upNo2, upName2, upNick2));
//遍历显示
doubleLinkedList.list();
System.out.println("--------------------------------------");
// 2.修改双向链表 end.
//------------------------------------------------------------------------------------------------------------------------------
// 3.删除双向链表的节点 begin
int n1 = 2;
int n2 = 6;
System.out.printf("三、要删除的编号为:%d 和 %d\n\n", n1, n2);
doubleLinkedList.delete(n1);
doubleLinkedList.delete(n2);
System.out.println("删除后的数据:\n");
//遍历显示
doubleLinkedList.list();
System.out.println("--------------------------------------");
// 3.删除双向链表的节点 end.
//------------------------------------------------------------------------------------------------------------------------------
// 4.添加双向链表的节点 begin
String[][] addArr = {
{"鲁智深", "武松"},
{"花和尚", "行者"}
};
System.out.printf("\n四、要添加的数据为:\n\n编号:%d ,姓名:%s,绰号:%s\n", n1, addArr[0][0], addArr[1][0]);
System.out.printf("编号:%d ,姓名:%s,绰号:%s\n\n", n2, addArr[0][1], addArr[1][1]);
System.out.println("添加后的数据:\n");
doubleLinkedList.addByOrder(new DHeroNode(n1, addArr[0][0], addArr[1][0]));
doubleLinkedList.addByOrder(new DHeroNode(n2, addArr[0][1], addArr[1][1]));
//遍历显示
doubleLinkedList.list();
System.out.println("--------------------------------------");
// 4.添加双向链表的节点 end.
//------------------------------------------------------------------------------------------------------------------------------
// 5.查询双向链表的一个节点 begin
int qn = 9; //要查询的位置
System.out.printf("五、要查询的编号为:%d\n\n", qn);
String[] strArr = doubleLinkedList.query(qn);
if(strArr[0] == "" && strArr[1] == ""){
System.out.println("error!");
}else{
System.out.printf("编号:%d,姓名:%s,绰号:%s\n\n", qn, strArr[0], strArr[1]);
}
System.out.println("--------------------------------------");
// 5.查询双向链表的一个节点 end.
//------------------------------------------------------------------------------------------------------------------------------
// 6.查询双向链表的一个节点的上一节点的数据,检验双链表是否成功 begin
int qn1 = 8; //要查询的位置
System.out.printf("六、查询的编号为 %d 的前一数据,\n\t\t\t\t检验双向链表是否成功!\n\n", qn1);
String[] strArr1 = doubleLinkedList.queryPrev(qn1);
if(strArr1[0] == "" && strArr1[1] == ""){
System.out.println("error!");
}else{
System.out.printf("编号:%d,姓名:%s,绰号:%s\n\n", qn1, strArr1[0], strArr1[1]);
}
// 6.查询双向链表的一个节点的上一节点的数据,检验双链表是否成功 end.
//------------------------------------------------------------------------------------------------------------------------------
//##########################################################
}
}
/**
* 二、链表管理类
*
* 说明:对双向链表数据结构的算法类,重要的操作类!
*
*/
class DoubleLinkedList{
//申请一个空白的头节点
private DHeroNode head = new DHeroNode(0, "", "");
/**
* 功能:按输入顺序添加
*
* 说明:按输入顺序添加数据进双向链表
*
* @param DHeroNode heroNode 要添加的数据节点
* @return void
**/
public void add(DHeroNode heroNode){
DHeroNode temp = head;
boolean flag = false;
while(true){
if(temp.next == null) break;
if(temp.next.no == heroNode.no) flag = true;
temp = temp.next;
}
if(flag){
System.out.printf("编号为%d的数据己经存在!\n", heroNode.no);
return;
}else{
temp.next = heroNode;
heroNode.prev = temp;
}
}
/**
* 功能:按排序顺序添加
*
* 说明:按排序顺序添加数据进双向链表
*
* @param DHeroNode heroNode 要添加的数据节点
* @return void
**/
public void addByOrder(DHeroNode heroNode){
DHeroNode temp = head;
boolean flag = false;
while(true){
if(temp.next == null)
break;
else if(temp.next.no > heroNode.no)
break;
else if(temp.next.no == heroNode.no)
flag = true;
temp = temp.next;
}
if(flag){
System.out.printf("编号为%d的数据已经存在!\n", heroNode.no);
return;
}else{
heroNode.next = temp.next;
temp.next = heroNode;
heroNode.prev = temp;
if(heroNode.next != null)
heroNode.next.prev = heroNode;
}
}
/**
* 功能:修改双向链表的数据
*
* @param DHeroNode heroNode 要修改的数据节点
* @return boolean 返回 true 成功或 false 失败的信息
**/
public boolean update(DHeroNode newNode){
if(head.next == null){
System.out.println("双向链表为空!");
return false;
}
DHeroNode temp = head;
boolean flag = false;
while(true){
if(temp.next == null)
break;
else if(temp.next.no == newNode.no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.next.name = newNode.name;
temp.next.nickname = newNode.nickname;
}else{
System.out.printf("没有找到编号为%d的数据!\n", newNode.no);
}
return true;
}
/**
* 功能:删除双向链表的一个节点
*
* @param int n 要删除的数据位置
* @return boolean 返回 true 成功或 false 失败的信息
**/
public boolean delete(int n){
DHeroNode temp = head;
boolean flag = false;
if(head.next == null){
System.out.println("链表为空!");
return false;
}
while(true){
if(temp.next == null)
break;
if(temp.next.no == n){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.next = temp.next.next;
if(temp.next != null)
temp.next.prev = temp;
return true;
}else{
System.out.printf("编号为%d的数据不存在!", n);
}
return false;
}
/**
* 功能:查询某一节点的数据
*
* @param int n 要查询的数据位置
* @return String[] 返回 error 空数组或有数据数组的信息
**/
public String[] query(int n){
String[] error = {"", ""};
if(head.next == null){
System.out.println("链表为空!");
return error;
}
DHeroNode temp = head.next;
boolean flag = false;
while(true){
if(temp.next == null) break;
if(temp.next.no == n){
flag = true;
break;
}
temp = temp.next;
}
if(temp.next != null)
temp = temp.next;
if(flag){
String[] tmp = {temp.name, temp.nickname};
return tmp;
}else{
System.out.printf("编号为%d的数据不存在!", n);
return error;
}
}
/**
* 功能:查询某一节点的后一数据
*
* 说明:检验双向链表是否成功
*
* @param int n 要查询的数据位置
* @return String[] 返回 error 空数组或有数据数组的信息
**/
public String[] queryPrev(int n){
String[] error = {"", ""};
if(head.next == null){
System.out.println("链表为空!");
return error;
}
DHeroNode temp = head.next;
boolean flag = false;
while(true){
if(temp.next == null) break;
if(temp.next.no == n){
flag = true;
break;
}
temp = temp.next;
}
if(temp.next != null)
temp = temp.next;
if(flag){
String[] tmp = {temp.prev.name, temp.prev.nickname};
return tmp;
}else{
System.out.printf("编号为%d的数据不存在!", n);
return error;
}
}
/**
* 功能:遍历显示数据
*
* @param none
* @return void
**/
public void list(){
if(head.next == null){
System.out.println("链表为空!");
return;
}
DHeroNode temp = head.next;
while(true){
if(temp == null) break;
System.out.println(temp);
temp = temp.next;
}
}
}
/**
* 三、双向链表的数据结构节点
*
* 说明:是重要的数据类
*
**/
class DHeroNode{
public int no;
public String name;
public String nickname;
public DHeroNode prev; //previous
public DHeroNode next;
public DHeroNode(int no, String name, String nickname){
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString(){
String str1 = "", str2 = "";
//由于界面显示混乱,排版
switch(name.length()){
case 1: str1 = ",...绰号:" ;break;
case 2: str1 = ",..绰号:" ;break;
case 3: str1 = ",.绰号:" ;break;
case 4: str1 = ",绰号:" ;break;
default: str1 = ",绰号:" ;
}
//由于界面显示混乱,排版
if(no < 10)
str2 = ", 姓名:" ;
else if(no >= 10 && no < 100)
str2 = ",姓名:" ;
else if(no >= 100)
str2 = ",姓名:" ;
return "编号:" + no + str2 + name + str1 + nickname;
}
}
三、程序执行后的效果:
1.检验双向链表是否成功?
2.完整的效果: