[C++]数据结构之单链表

来源:互联网 发布:residential 网络 编辑:程序博客网 时间:2024/05/16 09:40

2017/2/1 修改

///////////////////////////////////////  // LinkList.h : CLinkList 单链表类   //     #include <assert.h>    // 节点类   template <class Type>  class CNode {  // 方法  public :      CNode()      {          m_pNext = 0;      }         // 属性   public :      Type m_data;      CNode * m_pNext;  };    // 单链表类  template <class Type>  class CLinkList {  // 方法  public :      // 构造       CLinkList();      CLinkList(Type arrInitial[], int iLen);      // 析构      ~CLinkList();            // 销毁       void Destroy();            // 是否为空      bool IsEmpty();      // 取链表长度      int GetSize();            // 以序号查找节点(-1表示根节点, 超出链表范围返回尾结点)       CNode<Type> * GetNodeFromID(int iIndex);      CNode<Type> * operator [] (int iIndex);      // 以内容查找节点       CNode<Type> * GetNodeFromData(Type data);      // 以内容查找序号(失败返回-1)      int Find(Type data);            // 插入      bool AddAt(int iIndex, Type data);      // 在末尾处加入       bool AddBack(Type data);      // 删除      bool Delete(int iIndex);      bool Delete(int iIndex, Type * data);         // 属性  private :      // 头结点,尾结点       CNode<Type> * m_pHead, * m_pTail;            // 链表长度      int m_iSize;   };    // 构造  template <class Type>  CLinkList<Type>::CLinkList()  {      m_pHead = new CNode<Type>();      m_pTail = m_pHead;      m_iSize = 0;  }    // 构造  template <class Type>  CLinkList<Type>::CLinkList(Type arrInitial[], int iLen)  {      m_pHead = new CNode<Type>();      m_pTail = m_pHead;     m_pHead->m_pNext = 0;      m_iSize = 0;            for (int i = 1; i <= iLen; i++)          AddBack(arrInitial[i - 1]);  }    // 析构  template <class Type>  CLinkList<Type>::~CLinkList()  {      Destroy();      delete m_pHead;  }    // 销毁   template <class Type>  void CLinkList<Type>::Destroy()  {      CNode<Type> * p, * q;      p = m_pHead;      while(p)      {          q = p;          p = p->m_pNext;          delete q;      }      m_iSize = 0;  }    // 是否为空  template <class Type>  bool CLinkList<Type>::IsEmpty()  {      return (!m_iSize);      //return (m_pHead->m_pNext == 0);  }    // 以序号查找节点   template <class Type>  CNode<Type> * CLinkList<Type>::GetNodeFromID(int iIndex)  {      // 我们经常会需要在链表尾部添加节点,       // 如果频繁地使用 GetNodeFromID() 获取尾部节点,可能耗时较长,       // 因此这样写      if (iIndex >= GetSize() - 1)          return m_pTail;            if (iIndex == -1)          return m_pHead;            assert(!IsEmpty());      if (IsEmpty())          return 0;            assert(iIndex >= 0);      assert(iIndex < GetSize());      if (iIndex < 0 || iIndex >= GetSize())          return 0;                CNode<Type> * pTmp = m_pHead->m_pNext;      while(pTmp && iIndex)      {          pTmp = pTmp->m_pNext;          iIndex--;      }            return pTmp;  }    // 以内容查找节点   template <class Type>  CNode<Type> * CLinkList<Type>::GetNodeFromData(Type data)  {      assert(!IsEmpty());      if (IsEmpty())          return 0;            CNode<Type> * pTmp = m_pHead->m_pNext;      while (pTmp)      {          if (pTmp->m_data != data)              pTmp = pTmp->m_pNext;          else              return pTmp;      }            return 0;  }    // 以内容查找序号  template <class Type>  int CLinkList<Type>::Find(Type data)  {      assert(!IsEmpty());      if (IsEmpty())          return 0;            CNode<Type> * pTmp = m_pHead->m_pNext;      int i = 0;      while (pTmp)      {          if (pTmp->m_data != data)          {              pTmp = pTmp->m_pNext;              i++;          }           else              return i;      }      return -1;  }     // 取链表长度  template <class Type>  int CLinkList<Type>::GetSize()  {      /*     int iSize = 0;     CNode<Type> * pTmp = m_pHead->m_pNext;     while (pTmp)     {         iSize++;         pTmp = pTmp->m_pNext;     }          return iSize;     */            // 上面这种办法是可行的,但是有一个更简单的方法      return m_iSize;  }    // 以序号查找节点(运算符重载)  template <class Type>  CNode<Type> * CLinkList<Type>::operator [] (int iIndex)  {      return GetNodeFromID(iIndex);  }    // 插入  template <class Type>  bool CLinkList<Type>::AddAt(int iIndex, Type data)  {      CNode<Type> * p, * pLast;            pLast = GetNodeFromID(iIndex - 1);      assert(pLast);      if (!pLast)          return false;                p = new CNode<Type>();      p->m_data = data;      p->m_pNext = pLast->m_pNext;      pLast->m_pNext = p;            if (iIndex == GetSize())          m_pTail = p;            m_iSize++;       return true;  }    // 在末尾处加入   template <class Type>  bool CLinkList<Type>::AddBack(Type data)  {      return AddAt(GetSize(), data);  }    // 删除  template <class Type>  bool CLinkList<Type>::Delete(int iIndex)  {      CNode<Type> * pLast, * p;      pLast = GetNodeFromID(iIndex - 1);      assert(pLast);      if (!pLast)          return false;            p = pLast->m_pNext;      assert(p);      if (!p)          return false;            pLast->m_pNext = p->m_pNext;      delete p;            if (iIndex == GetSize())          m_pTail = pLast;            m_iSize--;      return true;  }    // 删除  template <class Type>  bool CLinkList<Type>::Delete(int iIndex, Type * data)  {      *data = GetNodeFromID(iIndex) -> m_data;      return Delete(iIndex);  }



///////////////////////////////////////// test1.cpp : 测试程序 // 从A中去除B中已存在的元素,保存到C中//#include <iostream>#include <cstdio>#include "LinkList.h"using namespace std;int main(){int arrA[] = {1, 2, 3, 4, 5, 6, 7};int arrB[] = {5, 7, 8, 9};CLinkList<int> linkA(arrA, sizeof(arrA) / sizeof(int));CLinkList<int> linkB(arrB, sizeof(arrB) / sizeof(int));linkA.Delete(4);linkB.AddAt(3, 2);printf("单链表 A 中的元素个数:%d\n", linkA.GetSize());printf("");for (int i = 1; i <= linkA.GetSize(); i++)cout << linkA[i - 1]->m_data << "  ";cout << endl;printf("单链表 B 中的元素个数:%d\n", linkB.GetSize());printf("");for (int i = 1; i <= linkB.GetSize(); i++)cout << linkB[i - 1]->m_data << "  ";cout << endl;CLinkList<int> linkC;for (int i = 1; i <= linkA.GetSize(); i++){if (linkB.Find(linkA[i - 1]->m_data) == -1)linkC.AddBack(linkA[i - 1]->m_data);}printf("单链表 A - B 中的元素个数:%d\n", linkC.GetSize());printf("");for (int i = 1; i <= linkC.GetSize(); i++)cout << linkC[i - 1]->m_data << "  ";cout << endl;return 0;}


///////////////////////////////////////// test2.cpp : 测试程序 // 合并链表 //#include <iostream>#include <cstdio>#include "LinkList.h"using namespace std;template <class Type>void PrintList(const char str[], CLinkList<Type> * list){printf("链表 %s 共有 %d 个元素:\n", str, list->GetSize());cout << "";for (int i = 1; i <= list->GetSize(); i++)cout << list->GetNodeFromID(i - 1)->m_data << " ";cout << endl;}int main(){int arr[] = {1, 8, 3, 4, 5};CLinkList<int> list1(arr, 5);PrintList("list1", &list1);int iData;list1.Delete(1, &iData);cout << endl << "删除链表中的第二个节点:" << iData << endl;PrintList("list1", &list1);cout << endl << "在第一个元素值等于4的节点前插入一个元素值为7的节点。" << endl;list1.AddAt(list1.Find(4), 7);PrintList("list1", &list1);cout << endl;int arr2[] = {9, 8, 6, 5};CLinkList<int> list2(arr2, 4);PrintList("list2", &list2);cout << endl << "把两条链表合并" << endl;for (int i = 1; i <= list2.GetSize(); i++)list1.AddBack(list2[i - 1]->m_data);PrintList("list1 + list2", &list1);}


-----------------------------------------------------------------------------------

下面是初始版本的代码:


不知道有没有错误。


///////////////////////////////////////// LinkList.h : CLinkList 单链表类 // #include <assert.h>// 节点类 template <class Type>class CNode {// 方法public :CNode(){m_pNext = 0;} // 属性 public :Type m_data;CNode * m_pNext;};// 单链表类template <class Type>class CLinkList {// 方法public :// 构造 CLinkList();CLinkList(Type arrInitial[], int iLen);// 析构~CLinkList();// 销毁 void Destroy();// 是否为空bool IsEmpty();// 取链表长度int GetSize();// 以序号查找节点(-1表示根节点) CNode<Type> * GetNodeFromID(int iIndex);CNode<Type> * operator [] (int iIndex);// 以内容查找节点 CNode<Type> * GetNodeFromData(Type data);// 以内容查找序号(失败返回-1)int Find(Type data);// 插入bool Insert(int iIndex, Type data);// 在末尾处加入 bool Add(Type data);// 删除bool Delete(int iIndex);bool Delete(int iIndex, Type * data); // 属性private :// 头结点  CNode<Type> * m_pHead; };// 构造template <class Type>CLinkList<Type>::CLinkList(){m_pHead = new CNode<Type>();m_pHead->m_pNext = 0;}// 构造template <class Type>CLinkList<Type>::CLinkList(Type arrInitial[], int iLen){m_pHead = new CNode<Type>();m_pHead->m_pNext = 0;for (int i = 1; i <= iLen; i++)Add(arrInitial[i - 1]);}// 析构template <class Type>CLinkList<Type>::~CLinkList(){Destroy();delete m_pHead;}// 销毁 template <class Type>void CLinkList<Type>::Destroy(){CNode<Type> * p, * q;p = m_pHead;while(p){q = p;p = p->m_pNext;delete q;}}// 是否为空template <class Type>bool CLinkList<Type>::IsEmpty(){return (m_pHead->m_pNext == 0);}// 以序号查找节点 template <class Type>CNode<Type> * CLinkList<Type>::GetNodeFromID(int iIndex){if (iIndex == -1)return m_pHead;assert(!IsEmpty());if (IsEmpty())return 0;assert(iIndex >= 0);assert(iIndex < GetSize());if (iIndex < 0 || iIndex >= GetSize())return 0;CNode<Type> * pTmp = m_pHead->m_pNext;while(pTmp && iIndex){pTmp = pTmp->m_pNext;iIndex--;}return pTmp;}// 以内容查找节点 template <class Type>CNode<Type> * CLinkList<Type>::GetNodeFromData(Type data){assert(!IsEmpty());if (IsEmpty())return 0;CNode<Type> * pTmp = m_pHead->m_pNext;while (pTmp){if (pTmp->m_data != data)pTmp = pTmp->m_pNext;elsereturn pTmp;}return 0;}// 以内容查找序号template <class Type>int CLinkList<Type>::Find(Type data){assert(!IsEmpty());if (IsEmpty())return 0;CNode<Type> * pTmp = m_pHead->m_pNext;int i = 0;while (pTmp){if (pTmp->m_data != data){pTmp = pTmp->m_pNext;i++;} elsereturn i;}return -1;} // 取链表长度template <class Type>int CLinkList<Type>::GetSize(){int iSize = 0;CNode<Type> * pTmp = m_pHead->m_pNext;while (pTmp){iSize++;pTmp = pTmp->m_pNext;}return iSize;}// 以序号查找节点(运算符重载)template <class Type>CNode<Type> * CLinkList<Type>::operator [] (int iIndex){return GetNodeFromID(iIndex);}// 插入template <class Type>bool CLinkList<Type>::Insert(int iIndex, Type data){CNode<Type> * p, * pLast;pLast = GetNodeFromID(iIndex - 1);assert(pLast);if (!pLast)return false;p = new CNode<Type>();p->m_data = data;p->m_pNext = pLast->m_pNext;pLast->m_pNext = p;return true;}// 在末尾处加入 template <class Type>bool CLinkList<Type>::Add(Type data){return Insert(GetSize(), data);}// 删除template <class Type>bool CLinkList<Type>::Delete(int iIndex){CNode<Type> * pLast, * p;pLast = GetNodeFromID(iIndex - 1);assert(pLast);if (!pLast)return false;p = pLast->m_pNext;assert(p);if (!p)return false;pLast->m_pNext = p->m_pNext;delete p;return true;}// 删除template <class Type>bool CLinkList<Type>::Delete(int iIndex, Type * data){*data = GetNodeFromID(iIndex) -> m_data;return Delete(iIndex);}


(顺便说一句,那个 GetNodeFromID() GetNodeFromData() 不能写成重载函数,因为后者的参数 data 的类型有可能是 int )


测试代码(从A中去除B中已存在的元素,保存到C中):

#include <iostream>#include <cstdio>#include "LinkList.h"using namespace std;int main(){int arrA[] = {1, 2, 3, 4, 5, 6, 7};int arrB[] = {5, 7, 8, 9};CLinkList<int> linkA(arrA, sizeof(arrA) / sizeof(int));CLinkList<int> linkB(arrB, sizeof(arrB) / sizeof(int));linkA.Delete(4);printf("单链表 A 中的元素个数:%d\n", linkA.GetSize());printf("");for (int i = 1; i <= linkA.GetSize(); i++)cout << linkA[i - 1]->m_data << "  ";cout << endl;printf("单链表 B 中的元素个数:%d\n", linkB.GetSize());printf("");for (int i = 1; i <= linkB.GetSize(); i++)cout << linkB[i - 1]->m_data << "  ";cout << endl;CLinkList<int> linkC;for (int i = 1; i <= linkA.GetSize(); i++){if (linkB.Find(linkA[i - 1]->m_data) == -1)linkC.Add(linkA[i - 1]->m_data);}printf("单链表 A - B 中的元素个数:%d\n", linkC.GetSize());printf("");for (int i = 1; i <= linkC.GetSize(); i++)cout << linkC[i - 1]->m_data << "  ";cout << endl;return 0;}


0 0
原创粉丝点击