"《算法导论》之‘线性表’":基于指针实现的单链表
对于单链表的介绍部分参考自博文数组、单链表和双链表介绍 以及 双向链表的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 }
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()
本篇博文的代码均托管到Taocode : http://code.taobao.org/p/datastructureandalgorithm/src/.