雙向鏈表相對於單向鏈表的優點:
1、單向鏈表在需要對列表尾部進行操作時,需要通過遍歷的方式獲取尾部的結點,很浪費時間
2、對於需要頻繁使用deleteFromTail()和addToTail()方法的程序,程序效率會非常低
3、雙向鏈表存儲了每個結點前面的結點,在對尾部進行操作時,能非常方便的獲取尾部的結點信息,方便對尾部進行操作,大大提高了程序效率
4、但是,雙向鏈表比單向鏈表多存儲了一個對象的引用,空間複雜度更高
C++代碼:
#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
//雙向鏈表結點類
class Node{
public:
int value; //結點數據
Node* pre; //前一個結點的指針
Node* next; //後一個結點的指針
//構造函數
Node(int aValue, Node* aPre=0, Node* aNext=0){
value = aValue;
pre = aPre;
next = aNext;
}
};
//雙向鏈表類
class DoublyLinkedList{
public:
Node* head; //鏈表頭
Node* tail; //鏈表尾
int length; //鏈表長度
//構造函數
DoublyLinkedList(){
head = tail = 0;
length = 0;
}
//判斷鏈表是否爲空
int isEmpty(){
return head == 0;
}
//判斷鏈表是否包含某個值
int contains(int value){
//遍歷鏈表查找值
for (Node* now=head; now!=0; now=now->next)
if (now->value == value)
return true;
return false;
}
//向鏈表頭添加結點
void addToHead(int value){
//如果鏈表爲空,直接添加
if (head == 0)
head = tail = new Node(value, 0, 0);
else
//鏈表不爲空,添加結點,更新head
head = head->pre = new Node(value, 0, head);
length++;
}
//向鏈表尾添加結點
void addToTail(int value){
//如果鏈表爲空,直接添加
if (head == 0)
head = tail = new Node(value, 0, 0);
//鏈表不爲空,添加結點,更新tail
else
tail = tail->next = new Node(value, tail, 0);
length++;
}
//向指定下標添加結點
void addNode(int value, int index){
//如果指定下標不合法,直接返回
if (index > length+1 || index <= 0) return ;
//如果鏈表爲空,且指定下標不是1,直接返回
if (head==0 && index!=1)
return ;
//如果鏈表爲空,需要新加入結點
if (head==0 && index==1){
head = tail = new Node(value, 0, 0);
//printf("Wrong.....\n");
}
//如果鏈表不爲空,需要在頭部加入結點
else if (index==1)
head = head->pre = new Node(value, 0, head);
else {
//鏈表不爲空,在鏈表中加入結點
int cnt = 0;
Node* aheadOfAdd=head;
//找到要加入結點的前一個結點
for(cnt=1; cnt+1<index; cnt++)
aheadOfAdd = aheadOfAdd->next;
//如果在尾部之後加入結點,更新tail
if (aheadOfAdd == tail)
tail = tail->next = new Node(value, tail, 0);
//否則直接加入
else
aheadOfAdd->next = aheadOfAdd->next->pre = new Node(value, aheadOfAdd, aheadOfAdd->next);
}
length++;
}
//刪除鏈表的第一個結點
int deleteFromHead(){
Node* deletedNode = 0;
int deletedValue = -1;
//如果鏈表爲空,直接返回
if (head == 0)
return -1;
//如果鏈表只有一個結點,刪除這個結點,更新head和tail
if (head == tail)
deletedNode = head;
//正常刪除
else{
deletedNode = head;
head = head->next;
head->pre = 0;
}
length--;
deletedValue = deletedNode->value;
delete deletedNode;
return deletedValue;
}
//刪除鏈表的最後一個結點
int deleteFromTail(){
Node* deletedNode = 0;
int deletedValue = -1;
//如果鏈表爲空,直接返回
if (head == 0)
return -1;
//如果鏈表只有一個結點,刪除這個結點,更新head和tail
if (head == tail){
deletedNode = head;
head = tail = 0;
}
//其他情況
else{
deletedNode = tail;
tail = tail->pre;
tail->next = 0;
}
length--;
deletedValue = deletedNode->value;
delete deletedNode;
return deletedValue;
}
//按照給定下標刪除結點
int deleteNode(int index){
//如果給定index明顯不合法,直接返回
if (index<=0 || index>length)
return -1;
//要刪除的結點和被刪除的值
Node* deletedNode = head;
int deletedValue = -1;
//如果鏈表爲空,直接返回
if (head == 0) return -1;
//如果鏈表只有一個元素且要求刪除其他的元素,直接返回
if (head == tail && index != 1)
return -1;
//如果鏈表只有一個元素且要求刪除該元素,更新head和tail
if (head == tail && index == 1){
deletedNode = head;
head = tail = 0;
}
//如果需要刪除鏈表頭結點
else if(index == 1){
deletedNode = head;
head = head->next;
head->pre = 0;
}
//如果需要刪除鏈表尾結點
else if(index == length){
deletedNode = tail;
tail = tail->pre;
tail->next = 0;
}
//其他情況
else{
int cnt;
for(deletedNode=head,cnt=1; cnt<index; cnt++, deletedNode=deletedNode->next);
deletedNode->pre->next = deletedNode->next;
deletedNode->next->pre = deletedNode->pre;
}
length--;
deletedValue = deletedNode->value;
delete deletedNode;
return deletedValue;
}
//打印鏈表
//從前向後和從後向前打印,確保前向和後向指針完全正確
void printSelf(){
printf("DoublyLinkedList: [");
for (Node* now=head; now!=0; now=now->next)
printf("%d, ", now->value);
printf("] ");
printf("Backside front: [");
for (Node* now=tail; now!=0; now=now->pre)
printf("%d, ", now->value);
printf("]\n\t\t");
printf("Head: %d\t\ttail: %d\t\tLength: %d\n", head->value, tail->value, length);
}
};
//測試程序
int main(){
DoublyLinkedList* list = new DoublyLinkedList();
list->addToHead(100);list->printSelf();
list->addToHead(200);list->printSelf();
list->addToTail(1);list->printSelf();
list->addToTail(2);list->printSelf();
list->addToTail(3);list->printSelf();
list->deleteFromTail();list->printSelf();
list->deleteFromTail();list->printSelf();
list->addNode(10000, 1);list->printSelf();
printf("\n\n");
list->deleteNode(5);list->printSelf();
printf("%d \n", list->isEmpty());
printf("123456--- %d \n", list->contains(123456));
printf("10000--- %d \n", list->contains(10000));
//list->deleteFromHead();list->printSelf();
//list->deleteFromHead();list->printSelf();
//list->printSelf();
}