下午上機的時候大概地實現了鏈表的基本功能。寫的時候也不是光是腦袋想,
就在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;
}