541 lines
12 KiB
C++
541 lines
12 KiB
C++
|
#include <iostream>
|
|||
|
#include <string>
|
|||
|
#include <functional>
|
|||
|
using namespace std;
|
|||
|
|
|||
|
|
|||
|
class CElement;
|
|||
|
/***
|
|||
|
* @brief 单链表容器
|
|||
|
*/
|
|||
|
class CSingleList
|
|||
|
{
|
|||
|
public:
|
|||
|
CSingleList();
|
|||
|
~CSingleList();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 插入..链表末尾插入
|
|||
|
* @return 成功返回非空指针,否则失败
|
|||
|
*/
|
|||
|
CElement* Insert(void* lpData, int iDataSize);
|
|||
|
/**
|
|||
|
* @brief 插入..链表指定位置插入
|
|||
|
* @return 成功返回非空指针,否则失败
|
|||
|
*/
|
|||
|
CElement* Insert(CElement* lpElement, void* lpData, int iDataSize);
|
|||
|
/**
|
|||
|
* @brief 删除
|
|||
|
*/
|
|||
|
void Delete(CElement*);
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 链首
|
|||
|
*/
|
|||
|
CElement* Begin();
|
|||
|
/**
|
|||
|
* @brief 下一个元素
|
|||
|
*/
|
|||
|
CElement* Next();
|
|||
|
/***
|
|||
|
* @brief 链尾
|
|||
|
*/
|
|||
|
CElement* End();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 是否是空链表
|
|||
|
* @return 空返回TRUE,否则返回FALSE
|
|||
|
*/
|
|||
|
bool Empty();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 反转
|
|||
|
*/
|
|||
|
void Reverse();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 检测环
|
|||
|
* @return 返回TRUE时表示链表存在环,否则不存在环.
|
|||
|
*/
|
|||
|
bool CheckCircle();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 合并2个有序的链表
|
|||
|
*/
|
|||
|
void Merge(CSingleList& lst, std::function<int(void* t1, void* t2)>);
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 删除倒数第K个结点
|
|||
|
*/
|
|||
|
void DeleteLastKth(int k);
|
|||
|
/**
|
|||
|
* @brief 求中间节点
|
|||
|
*/
|
|||
|
CElement* Center();
|
|||
|
private:
|
|||
|
void Insert(CElement* lpNewElement, CElement* lpCurElement, bool bBack = true);
|
|||
|
void Insert(CElement* lpNewElement);
|
|||
|
CElement* Tail();
|
|||
|
|
|||
|
CSingleList(CSingleList const & rhs);
|
|||
|
CSingleList& operator= (CSingleList const& rhs);
|
|||
|
private:
|
|||
|
/**头结点*/
|
|||
|
CElement* m_lpHead;
|
|||
|
/**哨兵*/
|
|||
|
CElement* m_lpSentinel;
|
|||
|
/**空结点,用于End()返回 */
|
|||
|
CElement* m_lpNull;
|
|||
|
/**当前结点. 枚举时使用. */
|
|||
|
CElement* m_lpCur;
|
|||
|
};
|
|||
|
|
|||
|
/***
|
|||
|
* @brief 单链表结点元素.
|
|||
|
*/
|
|||
|
class CElement
|
|||
|
{
|
|||
|
friend class CSingleList;
|
|||
|
protected:
|
|||
|
CElement();
|
|||
|
~CElement();
|
|||
|
public:
|
|||
|
/***
|
|||
|
* @brief 获取数据指针
|
|||
|
*/
|
|||
|
void* GetDataPtr();
|
|||
|
protected:
|
|||
|
/**下一个结点*/
|
|||
|
CElement* m_lpNext;
|
|||
|
void* m_lpData;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
void CreateList(CSingleList& lst)
|
|||
|
{
|
|||
|
//循环插入元素到链表尾
|
|||
|
for(int i=1; i<10;i++)
|
|||
|
{
|
|||
|
int* p = new int();
|
|||
|
*p = i;
|
|||
|
lst.Insert(p, 4);
|
|||
|
}
|
|||
|
}
|
|||
|
void PrintList(CSingleList& lst)
|
|||
|
{
|
|||
|
CElement* lpElement = lst.Begin();
|
|||
|
while(lpElement != lst.End())
|
|||
|
{
|
|||
|
std::cout<<*((int*)lpElement->GetDataPtr())<<std::endl;
|
|||
|
lpElement = lst.Next();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int main()
|
|||
|
{
|
|||
|
{
|
|||
|
/// 链表的基本操作,插入/枚举/删除
|
|||
|
CSingleList lst;
|
|||
|
CElement* lpElement = NULL;
|
|||
|
CreateList(lst);
|
|||
|
|
|||
|
std::cout<<"枚举链表当前的元素"<<std::endl;
|
|||
|
PrintList(lst);
|
|||
|
|
|||
|
std::cout<<"查找指定元素,并在指定元素后面插入新元素"<<std::endl;
|
|||
|
lpElement = lst.Begin();
|
|||
|
while(lpElement != lst.End())
|
|||
|
{
|
|||
|
if(*((int*)lpElement->GetDataPtr()) == 5)
|
|||
|
{
|
|||
|
int* p = new int();
|
|||
|
*p = 55;
|
|||
|
lst.Insert(lpElement,p, 4);
|
|||
|
break;
|
|||
|
}else{
|
|||
|
lpElement = lst.Next();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
std::cout<<"枚举链表当前的元素"<<std::endl;
|
|||
|
PrintList(lst);
|
|||
|
|
|||
|
std::cout<<"查找指定元素(数字是7的元素),并删除指定元素"<<std::endl;
|
|||
|
lpElement = lst.Begin();
|
|||
|
while(lpElement != lst.End())
|
|||
|
{
|
|||
|
if(*((int*)lpElement->GetDataPtr()) == 7)
|
|||
|
{
|
|||
|
lst.Delete(lpElement);
|
|||
|
break;
|
|||
|
}else{
|
|||
|
lpElement = lst.Next();
|
|||
|
}
|
|||
|
}
|
|||
|
std::cout<<"枚举链表当前的元素"<<std::endl;
|
|||
|
PrintList(lst);
|
|||
|
}
|
|||
|
|
|||
|
std::cout<<"--------------------------"<<std::endl;
|
|||
|
{
|
|||
|
/// 链表的反转
|
|||
|
CSingleList lst;
|
|||
|
CElement* lpElement = NULL;
|
|||
|
CreateList(lst);
|
|||
|
std::cout<<"反转"<<std::endl;
|
|||
|
lst.Reverse();
|
|||
|
PrintList(lst);
|
|||
|
}
|
|||
|
|
|||
|
std::cout<<"--------------------------"<<std::endl;
|
|||
|
{
|
|||
|
/// 检测环
|
|||
|
CSingleList lst;
|
|||
|
CElement* lpElement = NULL;
|
|||
|
CreateList(lst);
|
|||
|
std::cout<<"检测环"<<std::endl;
|
|||
|
bool bRet = lst.CheckCircle();
|
|||
|
if(bRet){
|
|||
|
std::cout<<"存在环."<<std::endl;
|
|||
|
}else{
|
|||
|
std::cout<<"不存在环."<<std::endl;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
std::cout<<"--------------------------"<<std::endl;
|
|||
|
{
|
|||
|
/// 有序链表合并
|
|||
|
CSingleList lst,lst2;
|
|||
|
CElement* lpElement = NULL;
|
|||
|
for(int i=1; i<10;i++)
|
|||
|
{
|
|||
|
int* p = new int();
|
|||
|
*p = i;
|
|||
|
if(i%2){
|
|||
|
lst2.Insert(p, 4);
|
|||
|
}else{
|
|||
|
lst.Insert(p, 4);
|
|||
|
}
|
|||
|
}
|
|||
|
std::cout<<"枚举链表当前的元素"<<std::endl;
|
|||
|
PrintList(lst);
|
|||
|
std::cout<<"......"<<std::endl;
|
|||
|
PrintList(lst2);
|
|||
|
lst.Merge(lst2,[](void* lpT1, void* lpT2) -> int{
|
|||
|
if(*((int*)lpT1) < *((int*)lpT2)){
|
|||
|
return -1;
|
|||
|
}else if(*((int*)lpT1) == *((int*)lpT2)){
|
|||
|
return 0;
|
|||
|
}else if(*((int*)lpT1) > *((int*)lpT2)){
|
|||
|
return 1;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
});
|
|||
|
std::cout<<"合并之后,打印当前链表."<<std::endl;
|
|||
|
PrintList(lst);
|
|||
|
}
|
|||
|
std::cout<<"--------------------------"<<std::endl;
|
|||
|
{
|
|||
|
/// 删除倒数第K个结点,并查看中间节点
|
|||
|
CSingleList lst;
|
|||
|
CreateList(lst);
|
|||
|
std::cout<<"删除倒数第0个结点"<<std::endl;
|
|||
|
lst.DeleteLastKth(0);
|
|||
|
PrintList(lst);
|
|||
|
CElement* lpCenter = lst.Center();
|
|||
|
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
|
|||
|
|
|||
|
std::cout<<"删除倒数第1个结点"<<std::endl;
|
|||
|
lst.DeleteLastKth(1);
|
|||
|
PrintList(lst);
|
|||
|
lpCenter = lst.Center();
|
|||
|
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
|
|||
|
|
|||
|
std::cout<<"删除倒数第3个结点"<<std::endl;
|
|||
|
lst.DeleteLastKth(3);
|
|||
|
PrintList(lst);
|
|||
|
lpCenter = lst.Center();
|
|||
|
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
|
|||
|
}
|
|||
|
std::cin.ignore();
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
CSingleList::CSingleList()
|
|||
|
{
|
|||
|
m_lpHead = new CElement();
|
|||
|
m_lpSentinel = new CElement();
|
|||
|
m_lpNull = new CElement();
|
|||
|
m_lpCur = NULL;
|
|||
|
m_lpHead->m_lpNext = m_lpSentinel;
|
|||
|
}
|
|||
|
CSingleList::~CSingleList()
|
|||
|
{
|
|||
|
if(NULL != m_lpSentinel)
|
|||
|
{
|
|||
|
delete m_lpSentinel;
|
|||
|
m_lpSentinel = NULL;
|
|||
|
}
|
|||
|
if(NULL != m_lpNull)
|
|||
|
{
|
|||
|
delete m_lpNull;
|
|||
|
m_lpNull = NULL;
|
|||
|
}
|
|||
|
if(NULL != m_lpHead)
|
|||
|
{
|
|||
|
delete m_lpHead;
|
|||
|
m_lpHead = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
CElement* CSingleList::Insert(void* lpData, int iDataSize)
|
|||
|
{
|
|||
|
CElement* lpNewElement = new CElement();
|
|||
|
if(NULL == lpNewElement)
|
|||
|
{
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
lpNewElement->m_lpData = lpData;
|
|||
|
Insert(lpNewElement, Tail());
|
|||
|
return lpNewElement;
|
|||
|
}
|
|||
|
CElement* CSingleList::Insert(CElement* lpElement, void* lpData, int iDataSize)
|
|||
|
{
|
|||
|
if((NULL == lpElement) || (End() == lpElement))
|
|||
|
{
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
CElement* lpNewElement = new CElement();
|
|||
|
if(NULL == lpNewElement)
|
|||
|
{
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
lpNewElement->m_lpData = lpData;
|
|||
|
Insert(lpNewElement, lpElement);
|
|||
|
return lpNewElement;
|
|||
|
}
|
|||
|
void CSingleList::Insert(CElement* lpNewElement, CElement* lpCurElement, bool bBack /*= true*/)
|
|||
|
{
|
|||
|
if(bBack){//插入到指定元素的后面
|
|||
|
lpNewElement->m_lpNext = lpCurElement->m_lpNext;
|
|||
|
lpCurElement->m_lpNext = lpNewElement;
|
|||
|
}else{//插入到指定元素的前面
|
|||
|
CElement* lpIter = m_lpSentinel;
|
|||
|
while(NULL != lpIter)
|
|||
|
{
|
|||
|
if(lpIter->m_lpNext == lpCurElement)
|
|||
|
{
|
|||
|
lpNewElement->m_lpNext = lpIter->m_lpNext;
|
|||
|
lpIter->m_lpNext = lpNewElement;
|
|||
|
break;
|
|||
|
}else{
|
|||
|
lpIter = lpIter->m_lpNext;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void CSingleList::Delete(CElement* lpElement)
|
|||
|
{
|
|||
|
if((NULL == lpElement) || (End() == lpElement))
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
CElement* lpCurElement = m_lpHead->m_lpNext;
|
|||
|
while(NULL != lpCurElement->m_lpNext)
|
|||
|
{
|
|||
|
if(lpCurElement->m_lpNext == lpElement)
|
|||
|
{
|
|||
|
lpCurElement->m_lpNext = lpCurElement->m_lpNext->m_lpNext;
|
|||
|
break;
|
|||
|
}else{
|
|||
|
lpCurElement = lpCurElement->m_lpNext;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
CElement* CSingleList::Tail()
|
|||
|
{
|
|||
|
CElement* lpCurElement = m_lpHead->m_lpNext;
|
|||
|
while(NULL != lpCurElement->m_lpNext)
|
|||
|
{
|
|||
|
lpCurElement = lpCurElement->m_lpNext;
|
|||
|
}
|
|||
|
return lpCurElement;
|
|||
|
}
|
|||
|
|
|||
|
CElement* CSingleList::Begin()
|
|||
|
{
|
|||
|
m_lpCur = NULL;
|
|||
|
if(NULL == m_lpHead->m_lpNext->m_lpNext)
|
|||
|
{
|
|||
|
m_lpCur = End();
|
|||
|
}else{
|
|||
|
m_lpCur = m_lpHead->m_lpNext->m_lpNext;
|
|||
|
}
|
|||
|
return m_lpCur;
|
|||
|
}
|
|||
|
|
|||
|
CElement* CSingleList::Next()
|
|||
|
{
|
|||
|
if((NULL == m_lpCur) || (End() == m_lpCur))
|
|||
|
{
|
|||
|
return m_lpCur;
|
|||
|
}
|
|||
|
m_lpCur = m_lpCur->m_lpNext;
|
|||
|
if(NULL == m_lpCur)
|
|||
|
{
|
|||
|
m_lpCur = End();
|
|||
|
}
|
|||
|
return m_lpCur;
|
|||
|
}
|
|||
|
|
|||
|
CElement* CSingleList::End()
|
|||
|
{
|
|||
|
return m_lpNull;
|
|||
|
}
|
|||
|
|
|||
|
bool CSingleList::Empty()
|
|||
|
{
|
|||
|
return Begin() == End();
|
|||
|
}
|
|||
|
|
|||
|
void CSingleList::Reverse()
|
|||
|
{
|
|||
|
if(Empty())
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
CElement* lpPre = NULL;
|
|||
|
CElement* lpTmp = NULL;
|
|||
|
CElement* lpCurElement = m_lpSentinel->m_lpNext;
|
|||
|
while(1)
|
|||
|
{
|
|||
|
lpTmp = lpCurElement->m_lpNext;
|
|||
|
lpCurElement->m_lpNext = lpPre;
|
|||
|
if(NULL == lpTmp)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
lpPre = lpCurElement;
|
|||
|
lpCurElement = lpTmp;
|
|||
|
}
|
|||
|
m_lpSentinel->m_lpNext = lpCurElement;
|
|||
|
}
|
|||
|
|
|||
|
bool CSingleList::CheckCircle()
|
|||
|
{
|
|||
|
if(Empty())
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
CElement* lpFast = m_lpSentinel->m_lpNext;
|
|||
|
CElement* lpSlow = m_lpSentinel->m_lpNext;
|
|||
|
while ((NULL != lpFast) && (NULL != lpFast->m_lpNext))
|
|||
|
{
|
|||
|
lpFast = lpFast->m_lpNext->m_lpNext;
|
|||
|
lpSlow = lpSlow->m_lpNext;
|
|||
|
if (lpFast == lpSlow)
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
void CSingleList::Merge(CSingleList& lst, std::function<int(void* t1, void* t2)> fnCompare)
|
|||
|
{
|
|||
|
CElement* lpL1 = Begin();
|
|||
|
CElement* lpL2 = lst.Begin();
|
|||
|
CElement* lpTail = NULL;
|
|||
|
|
|||
|
if(!fnCompare)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
int iRet = 0;
|
|||
|
while((lpL2 != lst.End()))
|
|||
|
{
|
|||
|
if(lpL1 != End())
|
|||
|
{
|
|||
|
iRet = fnCompare(lpL1->GetDataPtr(), lpL2->GetDataPtr());
|
|||
|
}else{
|
|||
|
iRet = -1;
|
|||
|
}
|
|||
|
CElement* lpNewElement = new CElement();
|
|||
|
if(NULL != lpNewElement)
|
|||
|
{
|
|||
|
lpNewElement->m_lpData = lpL2->GetDataPtr();
|
|||
|
if(lpL1 != End())
|
|||
|
{
|
|||
|
Insert(lpNewElement,lpL1, iRet <= 0);
|
|||
|
}else{
|
|||
|
if(NULL == lpTail)
|
|||
|
{
|
|||
|
lpTail = Tail();
|
|||
|
}
|
|||
|
Insert(lpNewElement,lpTail);
|
|||
|
}
|
|||
|
}
|
|||
|
lpL2 = lst.Next();
|
|||
|
lpL1 = Next();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void CSingleList::DeleteLastKth(int k)
|
|||
|
{
|
|||
|
int i = 1;
|
|||
|
if(k <= 0)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
CElement* lpFast = Begin();
|
|||
|
while((lpFast != End()) && (i < k))
|
|||
|
{
|
|||
|
lpFast = Next();
|
|||
|
++i;
|
|||
|
}
|
|||
|
if (lpFast == End())
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
CElement* lpSlow = Begin();
|
|||
|
CElement* lpPrev = NULL;
|
|||
|
while (NULL != lpFast->m_lpNext)
|
|||
|
{
|
|||
|
lpFast = lpFast->m_lpNext;
|
|||
|
lpPrev = lpSlow;
|
|||
|
lpSlow = Next();
|
|||
|
}
|
|||
|
if(NULL != lpPrev)
|
|||
|
{
|
|||
|
lpPrev->m_lpNext = lpPrev->m_lpNext->m_lpNext;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
CElement* CSingleList::Center()
|
|||
|
{
|
|||
|
CElement* lpFast = Begin();
|
|||
|
CElement* lpSlow = lpFast;
|
|||
|
while((NULL != lpFast->m_lpNext) && (NULL != lpFast->m_lpNext->m_lpNext))
|
|||
|
{
|
|||
|
lpFast = lpFast->m_lpNext->m_lpNext;
|
|||
|
lpSlow = lpSlow->m_lpNext;
|
|||
|
}
|
|||
|
return lpSlow;
|
|||
|
}
|
|||
|
|
|||
|
CElement::CElement()
|
|||
|
{
|
|||
|
m_lpNext = NULL;
|
|||
|
m_lpData = NULL;
|
|||
|
}
|
|||
|
CElement::~CElement()
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void* CElement::GetDataPtr()
|
|||
|
{
|
|||
|
return m_lpData;
|
|||
|
}
|