數據結構之雙向循環鏈表(C++實現)

下午上機的時候大概地實現了鏈表的基本功能。寫的時候也不是光是腦袋想,

就在word裏面畫了個粗糙的圖形,邊看邊寫。剛剛開始的時候功能可以不要

太多。把最基本的功能先實現,也就是數據定義,default constructor和destructor的功能

。然後測試,再增加功能,這樣後來寫的時候出錯的時候就會很明朗,至少不會是前面寫的

function出錯了。g++和vc下調試通過。main裏面的測試只是其中的一部分,寫的時候刪了許多。

雙向循環鏈表。首先它是一個環狀的,只是不是那麼圓,就像一個蛇咬住了自己的尾巴,那個發現苯環

的人就是晚上做了個夢,蛇咬住了自己的尾巴,然後他發現了苯環的結構。靈感源自生活,所以我們程序員

雖然總是對着電腦,但是請不要忘了,離開了電腦我們還有很廣闊的世界,說多了哈,剛剛打了下醬油。

接着上面的。然後它又是雙向的,所以它應該有2個指針,一個就是pre(前驅),一個就是next(後繼)。

就像右邊這個圖裏面畫的那樣,畫的不咋樣,這個還是到寢室後重新畫的。

清楚了它的結構,實現起來就比較簡單了,某些功能比單鏈表實現起來更簡單點,畢竟它是雙向的,所以很靈活,鏈表的用途還是很廣泛的,os裏面的各種作業調度算法的實現都是和鏈表息息相關。所以它的重要性可見一斑了。

如果你自己感興趣的話也可以自己去實現一下,C/C++都行。

鏈表的學習到這裏就結束了,對數據結構,linux C/C++有着濃厚興趣的同學可以加羣91926913一起交流下。

最後請看下面的代碼。

轉載請註明出處,謝謝!

dclink.h

 

#ifndef DCLINK_H
#define DCLINK_H
//雙向循環鏈表
typedef int datatype;
//方便修改
//當然也可以寫成模板來適應更多的數據類型
struct dclink{
	datatype data;//數據定義
	struct dclink *pre;
	struct dclink *next;//前驅和後繼指針
};
class DCLink
{
public:
	DCLink();//default constructor
	DCLink(datatype data);//單參constructor
	void add(datatype data);//添加data到鏈表中去
	datatype getData(int pos)const;//獲得指定位置的數據
	int deleteData(int pos);//刪除指定位置的數據
	int modify(int pos, datatype data);//更改指定位置的數據
	int insert(int pos, datatype data);//在指定位置插入數據
	void sort()const;//循環鏈表排序
	int rePrint()const;//雙向循環鏈表轉置沒啥意義,轉置輸出還有那麼點意義
	int print()const;//打印鏈表
	~DCLink();//destructor
	int getLength()const;//得到鏈表的長度
private:
	DCLink operator=(const DCLink &dcl){}//assignment constructor 禁止
	DCLink (const DCLink &dcl){}//copy constructor 禁止
	struct dclink *head;//頭指針
	struct dclink *cur;//當前指針
	int size;//大小
};
#endif


DCLink.cpp

#include "dclink.h"
#include <iostream>
//default constructor
DCLink::DCLink(){
	head = cur = NULL;//默認爲空
	size = 0;
}
DCLink::DCLink(datatype data){//單參constructor
	head = new struct dclink[1];//申請空間
	cur = head;//指向當前節點
	head->data = data;
	head->next = head->pre = head;//指向自身
	size = 1;
}
void DCLink::add(datatype data){//添加data到鏈表中去
	//默認添加到表尾
	struct dclink *dcl = new struct dclink[1];
	dcl->data = data;
	if (NULL != head){//表非空
		//當前節點爲第1號節點,它的後繼節點爲第2號節點
		struct dclink *temp = cur->next;//保持2號節點的位置
		cur->next = dcl;//1號節點的後繼和新增節點相連
		dcl->pre = cur;//新增節點的前驅和1號節點相連
		dcl->next = temp;//新增節點的後繼和2號節點相連
		temp->pre = dcl;//新增節點和2號節點的前驅相連
	}else {
		head = dcl;//新加節點成爲頭結點
		head->data = data;
		head->next = head->pre = head;//指向自身
	}//已經添加完畢,新增節點成爲當前節點
	cur = dcl;
	size++;//長度+1
}
int DCLink::deleteData(int pos){//刪除指定位置的數據
	if (size >= pos && pos > 0){//有數據並且沒有越界才顯示
		int count = 1;//計數
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;//直到到達指定的位置
			count++;
		}//先到達指定位置
		//分情況是因爲如果刪除最後一個節點會改變cur的狀態,掛空指針
		if (size == pos){
			if (1 == size){//只有一個節點的時候
				delete []temp;
				head = cur = NULL;//置空
				size--;//-1
				return 0;
			}else{//刪除最後一個節點
				cur = temp->pre;//向前移動一個位置
			}
		}else{//如果刪除第一個節點head會改變
			if (1 == pos){
				head = temp->next;//向後移動一個位置
			}
		}
		//當前節點爲0號節點,後繼節點爲1號節點,前驅節點爲-1號節點
		temp->pre->next = temp->next;//-1號節點的後繼和1號節點相連
		temp->next = temp->pre;//1號節點的前驅和-1號節點相連
		size--;//長度-1
		return 0;//成功返回0
	}
	return -1;//無數據或者越界返回-1
}
int DCLink::modify(int pos, datatype data){//更改指定位置的數據
	if (size >= pos && pos > 0){//有數據並且沒有越界才顯示
		int count = 1;//計數
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;
			count++;
		}
		temp->data = data;//更新
		return 0;
	}
	return -1;//無數據或者越界返回-1
}
int DCLink::insert(int pos, datatype data){//在指定位置插入數據
	if (0 == size && 1 == pos){
		this->add(data);//直接調用add函數
		return 0;
	}
	if (size >= pos && pos > 0){//有數據並且沒有越界才顯示
		int count = 1;//計數
		struct dclink *dcl = new struct dclink[1];
		dcl->data = data;
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;//直到到達指定的位置
			count++;
		}//先到達指定位置
		//分情況是因爲如果插入到第一個節點會改變head的狀態
		if (size == pos){
			if (1 == size){//只有一個節點的時候
				head = dcl;//當前結點成爲頭結點
				head->next = temp;//新結點的後繼和舊頭結點相連
				temp->pre = head;//舊頭結點的前驅和新結點相連
				head->pre = temp;//新結點的前驅和舊頭結點相連
				temp->next = head;//舊頭結點的後繼和新結點相連
			}else{//插入到尾結點的前面
				temp->pre->next = dcl;
				dcl->pre = temp->pre;
				dcl->next = temp;
				temp->pre = dcl;
			}
			size++;
			return 0;
		}else{
			if (1 == pos){//插入到第一個位置
				head = dcl;//當前結點成爲頭結點
				head->next = temp;//新結點的後繼和舊頭結點相連
				temp->pre = head;//舊頭結點的前驅和新結點相連
				head->pre = temp->pre;//新結點的前驅和舊頭結點相連
				temp->pre->pre = head;//舊頭結點的後繼和新結點相連
			}else {//插入到中間的其它位置
				temp->pre->next = dcl;
				dcl->pre = temp->pre;
				dcl->next = temp;
				temp->pre = dcl;
			}
			size++;
			return 0;
		}
	}
	return -1;//越界返回-1
}
datatype DCLink::getData(int pos)const{//獲得指定位置的數據
	if (size >= pos && pos > 0){//有數據並且沒有越界才顯示
		int count = 1;//計數
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;//比插入和刪除簡單很多
			count++;//+1,第一次寫的時候忘了+1,然後就固執地認爲getData肯定沒問題
			//可bug就在這裏
		}
		return temp->data;
	}
	return -1;//無數據或者越界返回-1
}
void DCLink::sort()const{//排序
	if (1 < size){
		//快速排序
		int i = 1;
		int j = 0;
		struct dclink *ohead = head;
		while (size != i){//循環size - 1次
			j = 0;//重置
			struct dclink *temp = ohead;//輔助指針
			while (j != size - i){
				if (ohead->data > temp->next->data){//交換排序
					ohead->data += temp->next->data;
					temp->next->data = ohead->data - temp->next->data;
					ohead->data -= temp->next->data;
				}
				temp = temp->next;//移動
				j++;
			}
			ohead = ohead->next;//前面j個數據已經排好
			i++;
		}
	}
}
int DCLink::rePrint()const{//打印鏈表
	if (NULL != head){//鏈表非空
		struct dclink *temp = head;
		int count = 0;//計數
		while (size != count){
			temp = temp->pre;
			std::cout<<temp->data<<std::endl;
			count++;
		}
		return 0;
	}
	return -1;//空表返回-1
}
int DCLink::print()const{//打印鏈表
	if (NULL != head){//鏈表非空
		struct dclink *temp = head;
		int count = 0;//計數
		while (size != count){
			std::cout<<temp->data<<"  ";
			temp = temp->next;
			count++;
		}
		return 0;
	}
	return -1;//空表返回-1
}
int DCLink::getLength()const{
	return size;
}//得到鏈表的長度
//destructor
DCLink::~DCLink()
{
	while (0 != size){//用size來控制析構的次數
		struct dclink *temp = head;//輔助指針
		head->pre->next = head->next;//讓head的前一個節點指向它的後一個節點
		head = head->next;//head後移動一個節點
		head->pre = temp->pre;//head還是指向前一個節點
		delete []temp;
		size--;
	}
}

int main(void){
	DCLink dcl;
	for (int i = 100; i > 0; i--)
		dcl.add(i);
	dcl.print();
	std::cout<<std::endl;
	dcl.sort();
 	dcl.print();
	dcl.modify(1,10);
	dcl.modify(5,44);
	dcl.modify(3,33);
	dcl.deleteData(5);
	dcl.deleteData(1);
	dcl.deleteData(3);
	dcl.deleteData(6);
	dcl.add(5);
	for (i = 1; i < 7; i++)
		std::cout<<dcl.getData(i)<<std::endl;
	
	std::cout<<"the sizeof DCLink is "<<dcl.getLength()<<std::endl;
	dcl.print();

	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章