生活随笔
收集整理的這篇文章主要介紹了
C++实现单链表
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
單鏈表的結(jié)構(gòu)有多種
這里介紹的鏈表有頭結(jié)點(diǎn)、有尾節(jié)點(diǎn)并且尾節(jié)點(diǎn)指向頭結(jié)點(diǎn)
SList.h
//****************/typedef?int?DataType;//節(jié)點(diǎn)類(復(fù)合形態(tài))
//struct?LinkNode?????
//{
// friend?class?SList;??????//將SList設(shè)為友元,便于SList類可以訪問節(jié)點(diǎn)類的私有成員
//public:
// LinkNode(const?DataType?x);
//private:
// DataType?_data;????//節(jié)點(diǎn)的數(shù)據(jù)
// LinkNode*?_next;????//指向該節(jié)點(diǎn)的下一個節(jié)點(diǎn)
//};//直接用struct定義LinkNode類,因?yàn)閟truct的成員默認(rèn)為公有數(shù)據(jù)成員,所以可直接訪問
struct?LinkNode??????//節(jié)點(diǎn)類(建議寫法)
{LinkNode(const?DataType?x);DataType?_data;????//節(jié)點(diǎn)的數(shù)據(jù)LinkNode*?_next;????//指向該節(jié)點(diǎn)的下一個節(jié)點(diǎn)
};
class?SList
{
public:SList();?????????//構(gòu)造函數(shù)SList(const?SList&?s);????????//拷貝構(gòu)造SList?&operator=(SList&?s);????//賦值運(yùn)算符的重載~SList();public:???//單鏈表的具體操作void?Uniqe();?????????//去重void?Merge(SList?&s);??//合并void?Sort();???????//冒泡void?Reverse();???//翻轉(zhuǎn)void?Swap(SList&?s);??????//交換void?PrintSList();???//打印鏈表void?PushBack(const?DataType&?x);????//在尾部插入一個節(jié)點(diǎn)void?Clear();?????????//鏈表置空void?PopBack();???????//刪除尾節(jié)點(diǎn)void?PushFront(DataType?x);??//頭插void?PopFront();????//刪除首節(jié)點(diǎn)void?Insert(LinkNode*?pos,?DataType?x);//固定位置插入一個節(jié)點(diǎn)void?Erase(LinkNode*?pos);????????//刪除某一節(jié)點(diǎn)LinkNode*?Find(DataType?x);???????//查找節(jié)點(diǎn)并返回這個節(jié)點(diǎn)的地址int?Amount();???//計算鏈表節(jié)點(diǎn)的數(shù)目void?Remove(DataType?x);?????//查找某節(jié)點(diǎn)并刪除void?RemoveAll(DataType?x);??????//刪除鏈表中所有的xprivate: LinkNode*?_head;?????//指向頭節(jié)點(diǎn)LinkNode*?_tail;????????//指向尾節(jié)點(diǎn)
};
//*********************//
SList.cpp ? (函數(shù)實(shí)現(xiàn))
//**********************/
#include<iostream>
using?namespace?std;
#include<assert.h>
#include"SList.h"LinkNode::LinkNode(const?DataType?x):_data(x),?_next(NULL){}SList::SList()?????????//構(gòu)造函數(shù):_head(NULL),?_tail(NULL){}SList::SList(const?SList&?s)??????????//拷貝構(gòu)造:_head(NULL),?_tail(NULL){if?(s._head?==?NULL){return;}LinkNode*?tmp?=?s._head;do{PushBack(tmp->_data);tmp?=?tmp->_next;}?while?(tmp?!=?s._head);}//賦值運(yùn)算符的重載(傳統(tǒng)方法)//SList?&?SList::operator=(const?SList&?s)????//{// if?(this?!=?&s)// {// _head?=?NULL;// _tail?=?NULL;// LinkNode*?tmp?=?s._head;// do{// PushBack(tmp->_data);// tmp?=?tmp->_next;// ?????}?while?(tmp?!=?s._head);// }// return?*this; //}//賦值運(yùn)算符的重載(高效寫法)/*void?SList::Swap(SList&?s)?????{swap(_head,?s._head);swap(_tail,?s._tail);}SList&??SList::operator=(SList?&s){if?(this?!=?&s){SList?tmp(s);Swap(tmp);}return?*this;}*/SList&??SList::operator=(SList?&s)?????//賦值運(yùn)算符的重載再優(yōu)化(推薦寫法){if?(this?!=?&s){swap(_head,?s._head);swap(_tail,?s._tail);}return?*this;}SList::~SList()????//析構(gòu){Clear();}void?SList::Reverse()???//鏈表逆置(利用頭插新節(jié)點(diǎn)的方法){if?(_head?==?NULL||_head->_next==_tail){return;}int?ret?=?Amount();_tail?=?new?LinkNode(_head->_data);LinkNode*?begin=NULL;LinkNode*?tmp?=?_tail;while?(--ret){LinkNode*?del?=?_head;_head?=?_head->_next;delete?del; //這里不要忘記做清理工作,否則內(nèi)存泄漏begin?=?new?LinkNode(_head->_data);begin->_next?=?tmp;_tail->_next?=?begin;tmp?=?begin;}_head?=?begin;}??//打印鏈表void?SList::PrintSList()??{//頭結(jié)點(diǎn)為空時,無需打印鏈表if?(_head==NULL){cout?<<?"This?SList?is?Empty?!"?<<?endl;return;}else{LinkNode*?tmp?=?_head;do{?cout?<<?tmp->_data?<<?"-->";tmp?=?tmp->_next;}?while?(tmp?!=?_head);cout?<<?endl;}}void?SList::PushBack(const?DataType&?x)????//在尾部插入一個節(jié)點(diǎn){//如果鏈表為空,插入節(jié)點(diǎn)后只有一個節(jié)點(diǎn),此時_head=_tailif?(_head?==?NULL){_head?=?new?LinkNode(x);_tail?=?_head;_tail->_next?=?_head;}else{_tail->_next?=?new?LinkNode(x);_tail?=?_tail->_next;_tail->_next?=?_head;}}void?SList::Clear()?????????//鏈表置空{(diào)LinkNode*?begin?=?_head;while?(begin?!=?_tail){_head?=?_head->_next;delete?begin;begin?=?_head;}_head?=?NULL;_tail?=?NULL;}void?SList::PopBack()????//尾刪{if?(_head?==?NULL){cout?<<?"This?SList?is?empty?!"?<<?endl;}else?if?(_head?==?_tail){delete?_head;_head?=?NULL;_tail?=?NULL;}else{LinkNode*?cur?=?_head;while?(cur->_next?!=?_tail){cur?=?cur->_next;}delete?_tail;_tail?=?cur;_tail->_next?=?_head;}}void?SList::PushFront(DataType?x)??//頭插{if?(_head?==?NULL){PushBack(x);}else{LinkNode*?tmp?=?_head;_head?=?new?LinkNode(x);_head->_next?=?tmp;_tail->_next?=?_head;}}void?SList::PopFront()????//刪除首節(jié)點(diǎn){if?(_head?==?NULL){cout?<<?"This?SList?is?empty?!"?<<?endl;return;}LinkNode*?tmp?=?_head;_head?=?_head->_next;_tail->_next?=?_head;delete?tmp;}//固定位置插入一個節(jié)點(diǎn)(這個函數(shù)需和Find函數(shù)搭配使用)//先用Find函數(shù)找到新節(jié)點(diǎn)需要插入的位置//(將Find函數(shù)的返回值傳給Insert函數(shù)的參數(shù)pos),再在pos節(jié)點(diǎn)后面插入新節(jié)點(diǎn)xvoid?SList::Insert(LinkNode*?pos,?DataType?x){assert(pos);if?(pos==_tail){PushBack(x);}else{LinkNode*?tmp?=?new?LinkNode(x);tmp->_next?=?pos->_next;pos->_next?=?tmp;}}//刪除某一節(jié)點(diǎn),同樣,要先找到該節(jié)點(diǎn)并傳參給Erase函數(shù)void?SList::Erase(LinkNode*?pos)????????{assert(pos);if?(pos?==?_tail){PopBack();}if?(pos?==?_head){PopFront();}else{LinkNode*?prev?=?_head;while?(prev->_next?!=?pos){prev?=?prev->_next;}prev->_next?=?pos->_next;delete?pos;}}LinkNode*?SList::Find(DataType?x)???????//查找節(jié)點(diǎn)并返回這個節(jié)點(diǎn)的地址{if?(_head?==?NULL){cout?<<?"This?SList?is?empty?!"?<<?endl;return?NULL;}else{LinkNode*?tmp?=?_head;do{if?(tmp->_data?==?x){return?tmp;}tmp?=?tmp->_next;}?while?(tmp?!=?_head);return?NULL;}}int?SList::Amount()???//計算鏈表節(jié)點(diǎn)的數(shù)目{if?(_head?==?NULL){return?0;}else{int?count?=?0;LinkNode*?cur?=?_head;while?(cur?!=?_tail){count++;cur?=?cur->_next;}return?++count;}}void?SList::Remove(DataType?x)??????//查找某節(jié)點(diǎn)并刪除{if?(_head?==?NULL){cout?<<?"This?SList?is?empty?!"?<<?endl;}else{LinkNode*?tmp?=?Find(x);if?(tmp?!=?NULL){Erase(tmp);}}}void?SList::RemoveAll(DataType?x)???????//刪除鏈表中所有的x{if?(_head?==?NULL){cout?<<?"This?SList?is?empty?!"?<<?endl;return;}
//如果鏈表不為空,設(shè)置left和right前后指針,從頭至尾遍歷一遍,delete節(jié)點(diǎn)的data為x的節(jié)點(diǎn)LinkNode*?left?=?_tail;LinkNode*?right?=?_head;int?count?=?Amount();while?(count--){//當(dāng)要刪掉的節(jié)點(diǎn)是頭節(jié)點(diǎn)時,需要注意頭節(jié)點(diǎn)要指向它的下一個節(jié)點(diǎn)//當(dāng)要刪掉的節(jié)點(diǎn)是尾節(jié)點(diǎn)時,需要注意尾節(jié)點(diǎn)要指向它的上一個節(jié)點(diǎn)//當(dāng)left和right指向同一塊要刪掉的節(jié)點(diǎn)時,將鏈表置空if?(right->_data?==?x){if?(_head?==?right)???{_head?=?_head->_next;}if?(_tail?==?right)???{_tail?=left;}if?(right?==?left)????{_head?=?NULL;_tail?=?NULL;return;}LinkNode*?tmp?=?right;right?=?right->_next;delete?tmp;left->_next?=?right;}else{left?=?right;right?=?right->_next;}} }void?SList::Uniqe()???????//去重(針對有序鏈表){assert(_head?&&_head!=?_tail);LinkNode*?left?=?_head;LinkNode*?right?=?_head->_next;while?(left?!=?_tail){while(left->_data?==?right->_data){LinkNode*?tmp?=?right;right?=?right->_next;left->_next?=?right;delete?tmp;}left?=?left->_next;right?=?right->_next;}}void?SList::Merge(SList?&s)????//合并(針對有序鏈表),合并后依然有序{//??1.?_head為空//??2.?鏈表s為空if?(_head?==?NULL){_head?=?s._head;_tail?=?s._tail;}if?(s._head?==?NULL){return;}//??3.?兩個鏈表都不為空LinkNode*?phead?=?_head;if?(phead->_data?<=?s._head->_data){phead?=?phead->_next;}else{_head?=?s._head;s._head?=?s._head->_next;}LinkNode*?cur?=?_head;while?(1){if?(phead->_data?<=?s._head->_data){_head->_next?=?phead;_head?=?_head->_next;if?(phead?==?_tail){_head->_next?=?s._head; _tail=s._tail;_tail->_next?=?cur;break;}phead?=?phead->_next;}else{_head->_next?=?s._head;_head?=?_head->_next;if?(s._head?==s._tail){_head->_next?=?phead;_tail->_next?=?cur;break;}s._head?=?s._head->_next;}}_head?=?cur;}void?SList::Sort()??????????????????????//冒泡排序{assert(_head);if?(_head?==?_tail){return;}int?size?=?Amount();for?(int?i?=?0;?i?<?size-1?;?i++) {LinkNode*?left?=?_head;LinkNode*?right?=?_head->_next;for?(int?j?=?0;?j?<?size?-?i-1?;?j++){ if?(left->_data>right->_data){swap(left->_data,?right->_data);}right?=?right->_next;left?=?left->_next;} }}
///************************
測試用例(Test.cpp)
#include"SList.h"
#include<stdlib.h>void?Test3()
{//排序?去重?合并cout?<<?"list?1:"?<<?endl;SList?list1;/*list1.PushBack(2);list1.PushBack(3);list1.PushBack(2);list1.PushBack(2);list1.PushBack(1);list1.PrintSList();list1.Sort();list1.PrintSList();list1.Uniqe();list1.PrintSList();*/list1.PushBack(5);list1.PushBack(3);list1.PushBack(8);list1.PushBack(2);list1.PushBack(9);list1.PushBack(10);list1.PushBack(2);list1.PushBack(2);list1.PushBack(1);list1.PrintSList();list1.Sort();list1.PrintSList();cout?<<?"list?2:"?<<?endl;SList?list2;list2.PushBack(1);list2.PushBack(6);list2.PushBack(4);list2.PushBack(0);list2.PushBack(7);list2.PrintSList();list2.Sort();list2.PrintSList();cout?<<?"list?1:"?<<?endl<<endl;list1.Merge(list2);list1.PrintSList();
}
void?Test2()
{SList?list1;list1.PushBack(1);list1.PushBack(3);list1.PushBack(4);list1.PushBack(2);list1.PushBack(6);list1.PrintSList();/*list1.RemoveAll(2);list1.PrintSList();*/SList?list2?=?list1;/*list2.PushBack(2);list2.PushBack(3);list2.PushBack(4);list2.PushBack(2);list2.PushBack(2);*/list2.PrintSList();list2.Reverse();list2.PrintSList();}
void?Test1()
{//SList?list1;//list1.PushBack(1);//list1.PushBack(2);//list1.PushBack(3);//list1.PushBack(4);//list1.PushBack(5);//list1.PrintSList();//list1.Remove(2);//list1.PrintSList();//int?num?=list1.Amount();//cout?<<"節(jié)點(diǎn)個數(shù):"<<?num?<<?endl;/*//檢驗(yàn)Erase函數(shù)LinkNode*?del?=?list1.Find(2);list1.Erase(del);list1.PrintSList();*//*//找到某節(jié)點(diǎn)并在其后插入新節(jié)點(diǎn)LinkNode*?In?=list1.Find(5);list1.Insert(In,?0);list1.PrintSList();*//*?//刪除頭結(jié)點(diǎn)list1.PopFront();list1.PrintSList();*///*//查找節(jié)點(diǎn)LinkNode*?ret=list1.Find(5);if?(ret?!=?NULL){cout?<<?"要查找的節(jié)點(diǎn)data是:"?<<?ret->_data?<<?endl;cout?<<?"要查找的節(jié)點(diǎn)adress是:"?<<ret<<?endl;}else{cout?<<?"not?exit?!"?<<?endl;}*//驗(yàn)證構(gòu)造函數(shù)//SList?list2(list1);//list2.PrintSList();//驗(yàn)證賦值運(yùn)算符的重載//SList?list3?=?list2;//list3.PrintSList();//驗(yàn)證析構(gòu)函數(shù)//list3.Clear();//list3.PrintSList();//驗(yàn)證尾刪和頭插///*list3.PopBack();//list3.PrintSList();*///list3.PushFront(0);//list3.PrintSList();
}int?main()
{//Test1();Test2();system("pause");
}
轉(zhuǎn)載于:https://blog.51cto.com/iynu17/1752937
總結(jié)
以上是生活随笔為你收集整理的C++实现单链表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。