算法與數據結構【C++】:雙向鏈表

雙向鏈表相對於單向鏈表的優點:


    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();
	
}

 

發佈了86 篇原創文章 · 獲贊 59 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章