一、認識雙向鍊錶
單向鍊錶不僅保存了目前的結點值,還保存了下一個結點的位址
定義一個雙向鍊錶的結點類:
結點中既要保存目前節點的值,還要保存此節點的前驅節點的位址和此節點的後繼節點的位址class DoubleNode{ public DoubleNode next; DoubleNode prev; int val; DoubleNode tail; public DoubleNode() {} public DoubleNode(int val) { this.val = val; } public DoubleNode(DoubleNode prev, int val, DoubleNode tail) { this.prev = prev; this.val = val; this.tail = tail; } }
定義一個雙向鍊錶類別:
既可以從前向後,也可以從後向前,所以在這個類別中,即保存一下頭結點,也保存一下尾結點的值public class DoubleLinkedList { private int size; private DoubleNode head; private DoubleNode tail; }二、雙向鍊錶的增刪改查1.插入頭插在目前鍊錶的頭部插入一個節點,讓目前鍊錶的頭結點head前驅指向要插入的節點node,然後讓node的後繼指向head,然後讓head = node,讓node成為鍊錶的頭結點
程式碼如下:
/** * 头插 */ public void addFirst(int val){ DoubleNode node = new DoubleNode(val); if (head == null){ head = tail = node; }else{ node.next = head; head.prev = node; head = node; } size++; }尾插和頭插一樣,只不過在鍊錶的尾部插入
程式碼如下:
public void addLast(int val){ DoubleNode node = new DoubleNode(val); if (head == null){ head = tail =node; }else{ tail.next = node; node.prev = tail; tail = node; } size++; }在index位置插入
#在索引為index的位置插入值為val的節點:
插入還是要找前驅節點,但雙向鍊錶找前驅節點比單向鍊錶找前驅節點要靈活很多,單向鍊錶只能從頭走到尾,假如此時有100個節點,要在索引為98的位置插入節點,那麼雙向鍊錶就可以從尾結點開始找,會方便很多#如何判斷從前向後找,還是從後向前找?
- 1.index 從前向後找,插入位置在前半部
- 2 .index > size / 2 – >從後向前找,插入位置在後半部
/**
* 在index位置插入
* @param index
* @param val
*/
public void add(int index,int val){
DoubleNode cur = new DoubleNode(val);
if (index < 0 || index > size){
System.err.println("add index illegal");
return;
}else{
if (index == 0){addFirst(val);}
else if (index == size){addLast(val);}
else{
DoubleNode prev = node(index-1);
DoubleNode next = prev.next;
cur.next = next;
next.prev = cur;
prev.next = cur;
cur.prev = prev;
}
}
size++;
}
/**
* 根据索引值找到对应的结点
* @param index
* @return
*/
private DoubleNode node(int index){
DoubleNode x = null;
if (index < size/2){
x = head;
for (int i = 0; i < index; i++) {
x = x.next;
}
}else{
x = tail;
for (int i = size - 1; i > index ; i--) {
x = x.prev;
}
}
return x;
}
2.修改
/**
* 修改双向链表index位置的结点值为newVal
*/
public int set(int index,int newVal){
DoubleNode dummyHead = new DoubleNode();
dummyHead.next = head;
DoubleNode prev = dummyHead;
DoubleNode cur = prev.next;
if (index < 0 || index > size - 1){
System.err.println("set index illegal");
}else{
for (int i = 0; i < index; i++) {
prev = prev.next;
cur = cur.next;
}
}
int oldVal = cur.val;
cur.val = newVal;
return oldVal;
}
3.查詢
/**
* 查询index位置的结点值
*/
public int get(int index){
DoubleNode dummyHead = new DoubleNode();
dummyHead.next = head;
DoubleNode prev = dummyHead;
DoubleNode cur = prev.next;
if (index < 0 || index > size - 1){
System.err.println("get index illegal");
}else{
for (int i = 0; i < index; i++) {
prev = prev.next;
cur = cur.next;
}
}
return cur.val;
}
4.刪除
刪除index位置的節點
#程式碼如下://删除链表index位置的结点
public void removeIndex(int index){
if (index < 0 || index > size - 1){
System.err.println("remove index illegal");
return;
}
DoubleNode cur = node(index);
unlink(cur);
}
/**
* 删除当前双向链表的node结点
* 分治法
* @param node
*/
private void unlink (DoubleNode node){
DoubleNode prev = node.prev;
DoubleNode successor = node.next;
//1.先处理node的前半部分
if (prev == null){
head = successor;
}else{
//前驱不为空的情况
prev.next = successor;
node.prev = null;
}
if (successor == null){
tail = prev;
}else{
successor.prev = prev;
node.next = null;
}
size--;
}
頭刪
呼叫刪除任意位置的節點即可
程式碼如下://头删
public void removeFirst(){
removeIndex(0);
}
尾刪
呼叫刪除任意位置的節點即可
程式碼如下://尾删
public void removeLast(){
removeIndex(size - 1);
}
刪除第一個值為val的節點
//删除第一个值为val的结点
public void removeValOnce(int val){
if (head == null){
return;
}
for (DoubleNode x = head;x != null;x = x.next){
if (x.val == val){
unlink(x);
break;
}
}
}
/**
* 删除当前双向链表的node结点
* 分治法
* @param node
*/
private void unlink (DoubleNode node){
DoubleNode prev = node.prev;
DoubleNode successor = node.next;
//1.先处理node的前半部分
if (prev == null){
head = successor;
}else{
//前驱不为空的情况
prev.next = successor;
node.prev = null;
}
if (successor == null){
tail = prev;
}else{
successor.prev = prev;
node.next = null;
}
size--;
}
刪除所有值為val的值
//删除链表中所有值为val的结点
public void removeAllVal(int val){
for (DoubleNode x = head;x != null;){
if (x.val == val){
//暂存一下x的下一个结点
DoubleNode next = x.next;
unlink(x);
x = next;
}else{
//val不是待删除的元素
x = x.next;
}
}
}
/**
* 删除当前双向链表的node结点
* 分治法
* @param node
*/
private void unlink (DoubleNode node){
DoubleNode prev = node.prev;
DoubleNode successor = node.next;
//1.先处理node的前半部分
if (prev == null){
head = successor;
}else{
//前驱不为空的情况
prev.next = successor;
node.prev = null;
}
if (successor == null){
tail = prev;
}else{
successor.prev = prev;
node.next = null;
}
size--;
}
以上是Java雙向鍊錶的增刪改查怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Springboot項目多數據源配置下的數據庫訪問性能問題排查本文針對一個Springboot項目中使用Atomikos進行多數據源配�...

Java項目打包成可執行JAR文件時遭遇NoClassDefFoundError難題很多Java開發者在將項目打包成可執行JAR文件時,可能會�...

關於IntelliJIDEA破解的分析方法在編程界,IntelliJ...

問題介紹:視頻質量提升是視頻處理中的一個重要環節,尤其是在處理低清晰度的視頻時,如何利用Java語言和�...

在處理SpringBoot應用中,我們經常會遇到如何正確接收請求參數的問題。特別是當參數格式不是常見的JSON時,更�...

Java中聲明ConcurrentHashMap時加static的影響在Java編程中,ConcurrentHashMap...

自定義線程池中的initialize()方法的作用詳解當你在配置自定義線程池時,可能會注意到有一個initialize()方法。很...

關於曲線積分中變量代換的疑問提問者遇到一個曲線積分問題,其中一個步驟的計算結果令其困惑。題目給出了...


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中