"《算法导论》之‘线性表’":基于指针实现的单链表

  对于单链表的介绍部分参考自博文数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

  1. 单链表介绍

  单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针。

   1.1 单链表的示意图

  

  表头为空,表头的后继节点是"节点10"(数据为10的节点),"节点10"的后继节点是"节点20"(数据为10的节点),...

   1.2 单链表添加节点

  

  在"节点10"与"节点20"之间添加"节点15"
  添加之前:"节点10" 的后继节点为"节点20"。
  添加之后:"节点10" 的后继节点为"节点15",而"节点15" 的后继节点为"节点20"。

  需要注意的是在链表头部和其他地方添加结点是不一样的。

  在链表头部添加结点的关键代码为:

1 NodePointer ptr = new Node();
2 ptr->data = val;
3 ptr->next = head;
4 head = ptr;

  在其他地方添加结点的关键代码为:

1 NodePointer ptr = new Node(), tmpPtr = head;
2 ptr->data = val;
3 while(...){...}
4 ptr->next = tmpPtr->next;
5 tmpPtr->next = ptr;

   1.3 单链表删除节点

  

  删除"节点30"
  删除之前:"节点20" 的后继节点为"节点30",而"节点30" 的后继节点为"节点40"。
  删除之后:"节点20" 的后继节点为"节点40"。

  需要注意的是在链表首部、尾部和其他地方删除结点是不一样的。

  在链表首部删除结点的关键代码为:

1 NodePointer ptr = head, tmpPtr;
2 ...if (pos == 0)                // 在链表第一个位置
3 {
4     head = ptr->next;
5     delete ptr;
6 }

  在链表尾部删除结点的关键代码为:

1 NodePointer ptr = head, tmpPtr;
2 while (...){...}
3 tmpPtr = ptr->next;
4 ptr->next = NULL;
5 delete tmpPtr;

  在其他地方删除结点的关键代码为:

1 NodePointer ptr = head, tmpPtr;
2 while(...){...}
3 tmpPtr = ptr->next;
4 ptr->next = tmpPtr->next;
5 delete tmpPtr;

  2. 代码实现

  对于单链表,我定义了一个这样的类LinkedList

 1 // linkedlist.h
 2 #ifndef LINKEDLIST
 3 #define LINKEDLIST
 4 
 5 #include <iostream>
 6 #include <cassert>
 7 
 8 using namespace std;
 9 
10 typedef int ElementType;
11 
12 class Node
13 {
14 public:
15     ElementType data;
16     Node * next;
17 };
18 typedef Node * NodePointer;
19 
20 
21 class LinkedList
22 {
23 public:
24     LinkedList();
25     virtual ~LinkedList();
26     LinkedList(const LinkedList& origlist);         // 拷贝构造函数
27     LinkedList& operator=(const LinkedList& origlist);  // 赋值运算符重载
28     void initList(ElementType * arr, int len);
29     bool isEmpty();
30     bool addNode(const int pos, const ElementType val);
31     bool deleteNode(const int pos);
32     void displayNodes();
33     NodePointer getNode(const int pos);
34     int getLenOfList();
35 
36 private:
37     NodePointer head;
38 
39 };
40 
41 #endif // LINKEDLIST

  实现代码如下:

  1 // linkedlist.cpp
  2 #include "linkedlist.h"
  3 
  4 LinkedList::LinkedList()
  5 {
  6     head = NULL;
  7 }
  8 
  9 LinkedList::~LinkedList()
 10 {
 11     NodePointer ptr = head, tmpPtr;
 12     while (ptr != NULL)
 13     {
 14         tmpPtr = ptr;
 15         ptr = ptr->next;
 16         delete tmpPtr;
 17     }
 18 }
 19 
 20 LinkedList::LinkedList(const LinkedList& origlist)
 21 {
 22     //head = origlist.head;        // 很容易写成这样,这样会造成浅拷贝
 23     NodePointer ptr = origlist.head;
 24     int i = 0;
 25     while (ptr != NULL)
 26     {
 27         addNode(i, ptr->data);
 28         ptr = ptr->next;
 29         i++;
 30     }
 31 }
 32 
 33 LinkedList& LinkedList::operator=(const LinkedList& origlist)
 34 {
 35     //head = origlist.head;        // 很容易写成这样,这样会造成浅拷贝
 36     NodePointer ptr = origlist.head;
 37     int i = 0;
 38     while (ptr != NULL)
 39     {
 40         addNode(i, ptr->data);
 41         ptr = ptr->next;
 42         i++;
 43     }
 44     return *this;
 45 }
 46 
 47 void LinkedList::initList(ElementType * arr, int len)
 48 {
 49     for (int i = 0; i < len; i++)
 50     {
 51         addNode(i, arr[i]);
 52     }
 53 }
 54 
 55 bool LinkedList::isEmpty()
 56 {
 57     return head == NULL;
 58 }
 59 
 60 bool LinkedList::addNode(const int pos, const ElementType val)
 61 {
 62     bool success = true;
 63     int len = getLenOfList();
 64     // assert(0 <= pos <= len);
 65     if (pos < 0 || pos > len)
 66     {
 67         cerr << "The node at position " << pos << " you want to add is less than zero or larger than "
 68              << "the length of list ." << endl;
 69         success = false;
 70         throw out_of_range("out_of_range");
 71     }
 72     else
 73     {
 74         NodePointer ptr = new Node();
 75         ptr->data = val;
 76         if (pos == 0)                // 如果添加的元素在第1个
 77         {
 78             ptr->next = head;
 79             head = ptr;
 80         }
 81         else                        // 其他
 82         {
 83             NodePointer tmpPtr = head;
 84             int count = 0;
 85             while (tmpPtr != NULL && count < pos - 1)
 86             {
 87                 tmpPtr = tmpPtr->next;
 88                 count++;
 89             }
 90             ptr->next = tmpPtr->next;
 91             tmpPtr->next = ptr;
 92         }
 93         
 94     }
 95 
 96     return success;
 97 }
 98 
 99 bool LinkedList::deleteNode(const int pos)
100 {
101     bool success = true;
102     int len = getLenOfList();
103     if (len == 0)
104     {
105         cerr << "There is no element in the list." << endl;
106         success = false;
107     }
108     else
109     {
110         NodePointer ptr = head, tmpPtr;
111         int count = 0;
112         // assert(0 <= pos <= len);
113         if (pos < 0 || pos > len - 1)
114         {
115             cerr << "The node at position " << pos << " you want to delete is less than zero or larger than "
116                 << "the length of list ." << endl;
117             success = false;
118             throw out_of_range("out_of_range");
119         }
120         else if (pos == 0)                // 在链表第一个位置
121         {
122             head = ptr->next;
123             delete ptr;
124         }
125         else if (pos == len - 1)        // 在链表最后一个位置
126         {
127             while (ptr != NULL && count < pos - 1)
128             {
129                 ptr = ptr->next;
130                 count++;
131             }
132             tmpPtr = ptr->next;
133             ptr->next = NULL;
134             delete tmpPtr;
135         }
136         else                            // 其他
137         {
138             while (ptr != NULL && count < pos - 1)
139             {
140                 ptr = ptr->next;
141                 count++;
142             }
143             tmpPtr = ptr->next;
144             ptr->next = tmpPtr->next;
145             delete tmpPtr;
146         }
147     }
148     return success;
149 }
150 
151 void LinkedList::displayNodes()
152 {
153     int len = getLenOfList();
154     if (len == 0)
155     {
156         cerr << "There is no element in the list." << endl;
157     }
158     else
159     {
160         NodePointer ptr = head;
161         int sequence = 0;
162         while (ptr != NULL)
163         {
164             cout << "Seq: " << sequence << "; Data: " << ptr->data << "."<< endl;;
165             ptr = ptr->next;
166             sequence++;
167         }
168     }
169 
170 }
171 
172 NodePointer LinkedList::getNode(const int pos)
173 {
174     int len = getLenOfList();
175     if (len == 0)
176     {
177         cerr << "There is no element in the list." << endl;
178         return NULL;
179     }
180     else
181     {
182         // assert(0 <= pos <= len);
183         if (pos < 0 || pos > len - 1)
184         {
185             cerr << "The item at position " << pos << " you want to get is less than zero or "
186                 << "larger than the length of list." << endl;
187             throw out_of_range("out_of_range");
188             // return NULL;
189         }
190         else
191         {
192             NodePointer ptr = head;
193             int count = 0;
194             while (ptr != NULL && count < pos)
195             {
196                 ptr = ptr->next;
197                 count++;
198             }
199             return ptr;
200         }
201     }
202 }
203 
204 int LinkedList::getLenOfList()
205 {
206     int len = 0;
207     NodePointer ptr = head;
208     while (ptr != NULL)
209     {
210         len++;
211         ptr = ptr->next;
212     }
213     return len;
214 }
linkedlist.cpp

  Boost单元测试代码如下:

  1 // BoostUnitTest.cpp
  2 #define BOOST_TEST_MODULE LinkedList_Test_Module
  3 
  4 #include "stdafx.h"
  5 #include "D:\VSProject\Algorithm\List\LinkedList\SingleLinkedList_BasedOnPointer\SingleLinkedList\SingleLinkedList\linkedlist.h"
  6 
  7 struct LinkedList_Fixture
  8 {
  9 public:
 10     LinkedList_Fixture()
 11     {
 12         testLinkedList = new LinkedList();
 13     }
 14     ~LinkedList_Fixture()
 15     {
 16         delete testLinkedList;
 17     }
 18 
 19     LinkedList * testLinkedList;
 20 
 21 };
 22 
 23 BOOST_FIXTURE_TEST_SUITE(LinkedList_Test_Suite, LinkedList_Fixture)
 24 
 25 
 26 BOOST_AUTO_TEST_CASE( LinkedList_Normal_Test )  
 27 {
 28     // isEmpty --------------------------------------------
 29     BOOST_REQUIRE(testLinkedList->isEmpty() == true);
 30 
 31     // getLenOfList ---------------------------------------
 32     BOOST_REQUIRE(testLinkedList->getLenOfList() == 0);
 33 
 34     // addNode & getNode  ---------------------------------
 35     BOOST_REQUIRE(testLinkedList->addNode(0, 0) == true);
 36     BOOST_REQUIRE((testLinkedList->getNode(0))->data == 0);
 37     BOOST_REQUIRE((testLinkedList->getNode(0))->next == NULL);
 38     BOOST_REQUIRE(testLinkedList->isEmpty() == false);
 39     BOOST_REQUIRE(testLinkedList->getLenOfList() == 1);
 40 
 41     BOOST_REQUIRE(testLinkedList->addNode(1, 2) == true);
 42     BOOST_REQUIRE((testLinkedList->getNode(1))->data == 2);
 43     BOOST_REQUIRE((testLinkedList->getNode(1))->next == NULL);
 44     BOOST_REQUIRE(testLinkedList->isEmpty() == false);
 45     BOOST_REQUIRE(testLinkedList->getLenOfList() == 2);
 46 
 47     BOOST_REQUIRE(testLinkedList->addNode(1, 1) == true);
 48     BOOST_REQUIRE((testLinkedList->getNode(1))->data == 1);
 49     BOOST_REQUIRE((testLinkedList->getNode(1))->next != NULL);
 50     BOOST_REQUIRE(testLinkedList->isEmpty() == false);
 51     BOOST_REQUIRE(testLinkedList->getLenOfList() == 3);
 52 
 53 
 54     // deleteNode -----------------------------------------
 55     BOOST_REQUIRE(testLinkedList->deleteNode(0) == true);
 56     BOOST_REQUIRE((testLinkedList->getNode(0))->data == 1);
 57     BOOST_REQUIRE(testLinkedList->getLenOfList() == 2);
 58 
 59     BOOST_REQUIRE(testLinkedList->deleteNode(1) == true);
 60     BOOST_REQUIRE((testLinkedList->getNode(0))->data == 1);
 61     BOOST_REQUIRE(testLinkedList->getLenOfList() == 1);
 62 
 63     BOOST_REQUIRE(testLinkedList->deleteNode(0) == true);
 64     BOOST_REQUIRE(testLinkedList->getLenOfList() == 0);
 65 
 66 
 67     // initList -------------------------------------------
 68     int arr[] = { 0, 1, 2 };
 69     int len = sizeof(arr) / sizeof(int);
 70     testLinkedList->initList(arr, len);
 71     BOOST_REQUIRE(testLinkedList->getLenOfList() == 3);
 72     BOOST_REQUIRE((testLinkedList->getNode(0))->data == 0);
 73     BOOST_REQUIRE((testLinkedList->getNode(1))->data == 1);
 74     BOOST_REQUIRE((testLinkedList->getNode(2))->data == 2);
 75     BOOST_REQUIRE((testLinkedList->getNode(2))->next == NULL);
 76 
 77     
 78 }
 79 
 80 BOOST_AUTO_TEST_CASE(LinkedList_Abnormal_Test)
 81 {
 82     int arr[] = { 0, 1, 2 };
 83     int len = sizeof(arr) / sizeof(int);
 84     testLinkedList->initList(arr, len);
 85 
 86     // addNode -------------------------------------------
 87     BOOST_REQUIRE_THROW(testLinkedList->addNode(-1, 100), out_of_range);
 88     BOOST_REQUIRE_THROW(testLinkedList->addNode(10, 100), out_of_range);
 89 
 90     // deleteNode ----------------------------------------
 91     BOOST_REQUIRE_THROW(testLinkedList->deleteNode(-1), out_of_range);
 92     BOOST_REQUIRE_THROW(testLinkedList->deleteNode(10), out_of_range);
 93 
 94     // getNode --------------------------------------------
 95     BOOST_REQUIRE_THROW(testLinkedList->getNode(-1), out_of_range);
 96     BOOST_REQUIRE_THROW(testLinkedList->getNode(10), out_of_range);
 97 
 98 }
 99 
100 BOOST_AUTO_TEST_CASE(LinkedList_CopyConstuctor_Test)
101 {
102     int arr[] = { 0, 1, 2 };
103     int len = sizeof(arr) / sizeof(int);
104     testLinkedList->initList(arr, len);
105 
106     //LinkedList * testLinkedList2(testLinkedList);        // 特别容易写成这样,这样导致的结果就是testLinkedList2和
107     //                                                     testLinkedList指向同一块内存这样的写法才是正确的
108     //                                                     该句等同于
109     //                                                     LinkedList * testLinkedList2;
110     //                                                     testLinkedList2 = testLinkedList;                                    
111     //LinkedList testLinkedList2(*testLinkedList);        // 要不就这样子定义,只不过此时testLinkedList2不是一个指针
112     LinkedList * testLinkedList3 = new LinkedList(*testLinkedList);
113     BOOST_REQUIRE(testLinkedList3->getLenOfList() == 3);
114     BOOST_REQUIRE((testLinkedList3->getNode(0))->data == 0);
115     BOOST_REQUIRE((testLinkedList3->getNode(1))->data == 1);
116     BOOST_REQUIRE((testLinkedList3->getNode(2))->data == 2);
117     BOOST_REQUIRE((testLinkedList3->getNode(2))->next == NULL);
118 }
119 
120 BOOST_AUTO_TEST_CASE(LinkedList_EqualOperator_Test)
121 {
122     int arr[] = { 0, 1, 2 };
123     int len = sizeof(arr) / sizeof(int);
124     testLinkedList->initList(arr, len);
125 
126     // LinkedList * testLinkedList2 = testLinkedList;    // 错误的写法
127     LinkedList * testLinkedList2 = new LinkedList();
128     *testLinkedList2 = *testLinkedList;
129 
130     BOOST_REQUIRE(testLinkedList2->getLenOfList() == 3);
131     BOOST_REQUIRE((testLinkedList2->getNode(0))->data == 0);
132     BOOST_REQUIRE((testLinkedList2->getNode(1))->data == 1);
133     BOOST_REQUIRE((testLinkedList2->getNode(2))->data == 2);
134     BOOST_REQUIRE((testLinkedList2->getNode(2))->next == NULL);
135 }
136 
137 BOOST_AUTO_TEST_SUITE_END()
BoostUnitTest.cpp

 

  本篇博文的代码均托管到Taocode : http://code.taobao.org/p/datastructureandalgorithm/src/.

 

posted @ 2014-10-26 22:55  峰子_仰望阳光  阅读(708)  评论(0编辑  收藏  举报