单链表的C++实现(采用模板类)
采用模板類實現的好處是,不用拘泥于特定的數據類型。就像活字印刷術,制定好模板,就可以批量印刷,比手抄要強多少倍!
此處不具體介紹泛型編程,還是著重敘述鏈表的定義和相關操作。?
?
?鏈表結構定義
定義單鏈表的結構可以有4方式。如代碼所示。
本文采用的是第4種結構類型
/*************************************************************************1、復合類:在Node類中定義友元的方式,使List類可以訪問結點的私有成員
*************************************************************************/
class?LinkNode
{
????friend?class?LinkList;
private:
????int?data;
????LinkNode?*next;
};
class?LinkList
{
public:
????//單鏈表具體操作
private:
????LinkNode?*head;
};?
/*************************************************************************
2、嵌套類:在List內部定義Node類,但是Node的數據成員放在public部分,使List
和Node均可以直接訪問Node的成員
*************************************************************************/
class?LinkList
{
public:
????//單鏈表具體操作
private:
????class?LinkNode
????{
????public:
????????int?data;
????????LinkNode?*next;
????};
????LinkNode?*head;
};?
/*************************************************************************
3、繼承:在Node類中把成員定義為protected,然后讓List繼承Node類,這樣就可以
訪問Node類的成員了。
*************************************************************************/
class?LinkNode
{
protected:
????int?data;
????LinkNode?*next;
};
class?LinkList?:?public?LinkNode
{
public:
????//單鏈表具體操作
private:
????LinkNode?*head;
};?
/*************************************************************************
4、直接用struct定義Node類,因為struct的成員默認為公有數據成員,所以可直接
訪問(struct也可以指定保護類型)。
*************************************************************************/
struct?LinkNode
{
????int?data;
????LinkNode?*next;
};
class?LinkList
{
public:
????//單鏈表具體操作
private:
????LinkNode?*head;
};?
?
單鏈表的模板類定義
使用模板類需要注意的一點是template<class T>必須定義在同一個文件,否則編譯器會無法識別。
如果在.h中聲明類函數,但是在.cpp中定義函數具體實現, 會出錯。所以,推薦的方式是直接在.h中定義。
/*?單鏈表的結點定義?*/template<class?T>
struct?LinkNode
{
????T?data;
????LinkNode<T>?*next;
????LinkNode(LinkNode<T>?*ptr?=?NULL){next?=?ptr;}
????LinkNode(const?T?&item,?LinkNode<T>?*ptr?=?NULL)????
????//函數參數表中的形參允許有默認值,但是帶默認值的參數需要放后面
????{
????????next?=?ptr;
????????data?=?item;
????}
};
/*?帶頭結點的單鏈表定義?*/
template<class?T>
class?LinkList
{
public:
????//無參數的構造函數
????LinkList(){head?=?new?LinkNode<T>;}
????//帶參數的構造函數
????LinkList(const?T?&item){head?=?new?LinkNode<T>(item);}
????//拷貝構造函數
????LinkList(LinkList<T>?&List);
????//析構函數
????~LinkList(){Clear();}
????//重載函數:賦值
????LinkList<T>&?operator=(LinkList<T>?&List);
????//鏈表清空
????void?Clear();
????//獲取鏈表長度
????int?Length()?const;
????//獲取鏈表頭結點
????LinkNode<T>*?GetHead()?const;
????//設置鏈表頭結點
????void?SetHead(LinkNode<T>?*p);
????//查找數據的位置,返回第一個找到的滿足該數值的結點指針
????LinkNode<T>*?Find(T?&item);
????//定位指定的位置,返回該位置上的結點指針
????LinkNode<T>*?Locate(int?pos);
????//在指定位置pos插入值為item的結點,失敗返回false
????bool?Insert(T?&item,?int?pos);
????//刪除指定位置pos上的結點,item就是該結點的值,失敗返回false
????bool?Remove(int?pos,?T?&item);
????//獲取指定位置pos的結點的值,失敗返回false
????bool?GetData(int?pos,?T?&item);
????//設置指定位置pos的結點的值,失敗返回false
????bool?SetData(int?pos,?T?&item);
????//判斷鏈表是否為空
????bool?IsEmpty()?const;
????//打印鏈表
????void?Print()?const;
????//鏈表排序
????void?Sort();
????//鏈表逆置
????void?Reverse();
private:
????LinkNode<T>?*head;
};
?
定位位置??
/* 返回鏈表中第pos個元素的地址,如果pos<0或pos超出鏈表最大個數返回NULL */ template<class T> LinkNode<T>* LinkList<T>::Locate(int pos) {int i = 0;LinkNode<T> *p = head;if (pos < 0)return NULL;while (NULL != p && i < pos){p = p->next;i++;}return p; }?
插入結點
單鏈表插入結點的處理如圖?
?
?圖:單鏈表插入操作
要在p結點后插入一個新結點node,(1)要讓node的next指針指向p的next結點;(2)再讓p的next指向node結點(即斷開圖中的黑色實線,改成紅色虛線指向node)
接下來:node->next = p->next;?p->next = node;?
template<class T> bool LinkList<T>::Insert(T &item, int pos) {LinkNode<T> *p = Locate(pos);if (NULL == p)return false;LinkNode<T> *node = new LinkNode<T>(item);if (NULL == node){cerr << "分配內存失敗!" << endl;exit(1);}node->next = p->next;p->next = node;return true; }?
刪除結點
刪除結點的處理如圖:
?
圖:單鏈表刪除?
刪除pos位置的結點,如果這個位置不存在結點,則返回false;
如果找到對應結點,則通過實參item輸出要刪除的結點的數值, 然后刪除結點并返回true。
template<class T> bool LinkList<T>::Remove(int pos, T &item) {LinkNode<T> *p = Locate(pos);if (NULL == p || NULL == p->next)return false;LinkNode<T> *del = p->next;p->next = del->next;item = del->data;delete del;return true; }?
清空鏈表?
遍歷整個鏈表,每次head結點的next指針指向的結點,直到next指針為空。
最后保留head結點。?
template<class T> void LinkList<T>::Clear() {LinkNode<T> *p = NULL;//遍歷鏈表,每次都刪除頭結點的next結點,最后保留頭結點while (NULL != head->next){p = head->next;head->next = p->next; //每次都刪除頭結點的next結點 delete p;} }?
求鏈表長度和打印鏈表
著兩個功能的實現非常相近,都是遍歷鏈表結點,不贅述。?
template<class T> void LinkList<T>::Print() const {int count = 0;LinkNode<T> *p = head;while (NULL != p->next){p = p->next;std::cout << p->data << " ";if (++count % 10 == 0) //每隔十個元素,換行打印cout << std::endl;} }template<class T> int LinkList<T>::Length() const {int count = 0;LinkNode<T> *p = head->next;while (NULL != p){p = p->next;++count;}return count; }?
單鏈表倒置
單鏈表的倒置處理如圖:?
圖:單鏈表倒置?
(1)初始狀態:prev = head->next; curr = prev->next;
(2)讓鏈表的第一個結點的next指針指向空
(3)開始進入循環處理,讓next指向curr結點的下一個結點;再讓curr結點的next指針指向prev。即:next = curr->next; curr->next = prev;?
(4)讓prev、curr結點都繼續向后移位。即:prev = curr; curr = next;
(5)重復(3)、(4)動作,直到curr指向空。這時循環結束,讓haed指針指向prev,此時的prev是倒置后的第一個結點。即:head->next = prev;
template<class T> void LinkList<T>::Reverse() {LinkNode<T> *pre = head->next;LinkNode<T> *curr = pre->next;LinkNode<T> *next = NULL;head->next->next = NULL;while (curr){next = curr->next;curr->next = pre;pre = curr;curr = next;}head->next = pre; }?
?
?
?
?
轉載于:https://www.cnblogs.com/jingmoxukong/p/3827011.html
總結
以上是生活随笔為你收集整理的单链表的C++实现(采用模板类)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win8.1 USB启动盘制作(不支持U
- 下一篇: PHP为什么以及什么时候使用单例模式?