template class slist
node(t data)
};node* head;
node* tail;
int size;
public:
slist();
//複製建構函式
slist(const slist& sl);
~slist();
//尾插
void slistpushback(t data);
//尾刪
void slistpopback();
//頭插
void slistpushfront(t data);
//頭刪
void slistpopfront();
//指定結點後插入
void slistinsertafter(node* pos, t data);
//刪除指定結點
void slisterase(node* pos);
//查詢第乙個值為data的結點
node* slistfind(t data);
//刪除第乙個值為data的結點
void slistremove(t data);
//刪除全部值為data的結點
void slistremoveall(t data);
//逆置鍊錶
slist slistinversion();
//得到第乙個結點的位址
node* getfront() const
//得到最後乙個結點的位址
node* getback() const
//得到鍊錶中結點個數
int getsize() const
//判斷鍊錶是否為空
bool empty() const
//賦值運算子
slist& operator=(const slist& sl);
//合併兩個鍊錶
slist operator+(const slist& sl);
//過載
t operator(int i);
//cout《過載
template friend std::ostream& operator<<(std::ostream& os, const slist& sl);
};
得到第乙個結點的位址,得到最後乙個結點的位址,得到鍊錶中結點個數,判斷鍊錶是否為空,這幾條較為簡短的函式直接隱式內聯實現。
友元函式需要額外加上template
建構函式
templateslist::slist()
複製建構函式:因為類的成員中有指標指向new分配的空間,所以一定要顯示的定義複製建構函式和賦值運算子的過載函式,否則預設生成的函式只會賦值指標,使兩個物件的成員指標指向同一塊記憶體,物件析構是會重複釋放記憶體。
templateslist::slist(const slist& sl)
this->size = sl.size;
}else
}
析構函式:雖然建構函式沒有動態開闢記憶體,但是新增結點的函式開闢的記憶體一定要在這裡釋放掉。
templateslist::~slist()
}
尾插:這個類模板中不光有鍊錶的頭指標,還定義了指向最後乙個有效結點的尾指標,和記錄有效結點數的size,以方便操作,不管如何插入或是刪除,都要記得調整好尾指標的位置和size的值
templatevoid slist::slistpushback(t data)
else
++size;
}
尾刪:head == nullptr 時,不執行任何操作直接退出。
templatevoid slist::slistpopback()
else
node->next = nullptr;
delete tail;
tail = node;
}--size;
}}
頭插
templatevoid slist::slistpushfront(t data)
++size;
}
頭刪
templatevoid slist::slistpopfront()
--size;
}}
指定結點後插入:可以配合find使用
templatevoid slist::slistinsertafter(node* pos, t data)
node = node->next;
}node = new node(data);
node->next = pos->next;
pos->next = node;
if (tail->next != nullptr)
++size;
}
刪除指定結點
templatevoid slist::slisterase(node* pos)
else if (tail != nullptr && pos == tail)
else
node = node->next;
}node->next = pos->next;
delete pos;
--size;
}}
查詢第乙個值為data的結點:返回值前加上typename說明slist::node*是乙個型別,否則編譯器會認為這是乙個定義
templatetypename slist::node* slist::slistfind(t data)
}return node;
}
刪除第乙個值為data的結點
templatevoid slist::slistremove(t data)
刪除全部值為data的結點
templatevoid slist::slistremoveall(t data)
}
逆置鍊錶:頭刪和頭插的交替運用
templateslistslist::slistinversion()
return newsl;
}
賦值運算子:先判斷是否為自我賦值,賦值時要先釋放掉原先的記憶體空間,否則頭指標指向新記憶體後,原空間沒有指標能找到,造成記憶體洩漏
templateslist& slist::operator=(const slist& sl)
if (sl.head != nullptr)
this->size = sl.size;
}else
}return *this;
}
合併兩個鍊錶:過載加號來實現兩個鍊錶的合併,這裡要為合併後的鍊錶申請新的空間(複製原來的兩個鍊錶,把結點給它),否則會損壞原鍊錶。同樣為了不損換原鍊錶,必須有乙個物件來接收合併後的鍊錶(可以是連個原鍊錶之一)
templateslist& slist::operator+(const slist& sl)
過載
templatet slist::operator(int i)
return node->data;
}return false;
}
cout《過載:slist::node* node = sl.head
本來是想這樣寫的,但是這個友元函式不知道為什麼無法訪問類的私有成員,在網上找的方法說operator《但是我試了沒用,最後用auto交給編譯器自行解決了,教訓就是最好給需要訪問的私有成員定義get()和set()方法來實現訪問,而不要直接訪問。
templatestd::ostream& operator<<(std::ostream& os, const slist& sl)
return os;
}
資料結構 無頭結點的單鏈表
start reading 頭結點是用來標記單鏈表的乙個標誌,有些時候我們可以不使用頭結點,這時候操作就完全不一樣了。如何建立乙個無頭結點的單鏈表?不能在頭結點的資料域中放資料再變成假的第乙個資料節點在進行操作,那是自己騙自己。在單鏈表中我們直接頭結點進行解引用,但無頭結點的鍊錶最初其實就是乙個指標...
無頭單鏈表
鍊錶有單鏈表 雙鏈表和雙向迴圈鍊錶,每種鍊錶都有無頭和帶頭兩種,帶頭就是頭結點不存放資料元素 ifndef linklist h define linklist h include stdio.h include assert.h include string.h include malloc.h ...
無頭結點單鏈表實現 考研資料結構C C
屬於線性表的一種,採用鏈式儲存的儲存結構。優點 空間動態分配,不要求連續的大片空間。插入刪除方便 時間複雜度低 缺點 不能隨機訪問。相對於帶頭結點的單鏈表 插入 刪除不統一 實現比較複雜 演算法效能 include include 無頭結點的單鏈表的實現 typedef struct nodenod...