对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表)。现在我们就来看看怎么用数组来实现单链表。
1. 定义单链表中结点的数据结构
1 typedef int ElementType; 2 class NodeType 3 { 4 public: 5 ElementType data; 6 int next; 7 };
该结点包括了两个元素,其一是数据,另一个是指向下一个结点的“指针”(在这篇文章中实际上是指用于实现单链表的数组的下标。)
2. 定义一个的数组
1 const int CAPACITY = 1024; 2 NodeType node[CAPACITY];
在内存中该数组的结构如下图:
3. 定义指向单链表第1个结点的“指针”
1 int head;
4. 一个简单的单链表例子
我们假设单链表只有3个结点,并且3个结点从左到右分别位于数组node中第0、1、2位置,如下图:
head指向链表中的第1个结点。该结点存储于数组node的第0位置,data为111,next指向下一结点。其他以此类推。
需要注意的是链表的中最后一个结点(即上图中的第3个结点)的next被置为-1,表示不指向任何结点。
更为重要的是,这三个结点是可以位于数组node中的任一位置的,只要他们之间保持这种链接的关系。
5. 实际程序实现
在实际程序实现中,为了便于判断数组中哪一个元素已经被使用,我在原单链表的结点数据结构中又添加了一个判断位,如下:
1 typedef int ElementType; 2 class NodeType 3 { 4 public: 5 NodeType() { data = 0; next = NULL_VALUE; isFree = true; }; 6 ~NodeType() {}; 7 ElementType data; 8 int next; 9 bool isFree; // 标志位,为true表示该结点可用,反之不可用 10 };
其余的程序摘录如下:
1 #ifndef SINGLELINKEDLIST 2 #define SINGLELINKEDLIST 3 4 #include <iostream> 5 #include <cassert> 6 using namespace std; 7 8 const int CAPACITY = 1024; 9 const int NULL_VALUE = -1; 10 11 typedef int ElementType; 12 class NodeType 13 { 14 public: 15 NodeType() { data = 0; next = NULL_VALUE; isFree = true; }; 16 ~NodeType() {}; 17 ElementType data; 18 int next; 19 bool isFree; // 标志位,为true表示该结点可用,反之不可用 20 }; 21 22 class LinkedList 23 { 24 public: 25 LinkedList(); 26 virtual ~LinkedList(); 27 void initList(ElementType * arr, int len); 28 bool isEmpty(); 29 int findFreeNode(); 30 bool addNode(const int pos, const ElementType val); 31 bool deleteNode(const int pos); 32 void displayNodes(); 33 NodeType getNode(const int pos); 34 int getLenOfList(); 35 36 private: 37 NodeType node[CAPACITY]; 38 int head; 39 40 }; 41 42 43 #endif;
1 #include "linkedlist.h" 2 3 LinkedList::LinkedList() 4 { 5 head = NULL_VALUE; 6 } 7 8 LinkedList::~LinkedList() 9 { 10 for (int i = 0; i < CAPACITY; i++) 11 { 12 node[i].data = 0; 13 node[i].next = NULL_VALUE; 14 node[i].isFree = true; 15 } 16 } 17 18 void LinkedList::initList(ElementType * arr, int len) 19 { 20 for (int i = 0; i < len; i++) 21 { 22 int tmp = arr[i]; 23 addNode(i, tmp); 24 } 25 } 26 27 bool LinkedList::isEmpty() 28 { 29 return head == NULL_VALUE; 30 } 31 32 int LinkedList::findFreeNode() 33 { 34 int i = 0; 35 while (node[i].isFree == false) 36 { 37 i++; 38 if (i == CAPACITY) // 如果找不到可用的结点,返回NULL_VALUE 39 { 40 return NULL_VALUE; 41 } 42 } 43 return i; 44 } 45 46 bool LinkedList::addNode(const int pos, const ElementType val) 47 { 48 bool success = true; 49 int len = getLenOfList(); 50 if (len == CAPACITY) 51 { 52 cerr << "There is no space in the list." << endl; 53 success = false; 54 } 55 else 56 { 57 // assert(0 <= pos <= CAPACITY); 58 if (pos < 0 || pos > len) 59 { 60 cerr << "The node at position " << pos << " you want to add is less than zero or larger than " 61 << "the capacity of list ." << endl; 62 success = false; 63 throw out_of_range("out_of_range"); 64 } 65 else 66 { 67 int freeNode = findFreeNode(); 68 node[freeNode].data = val; 69 node[freeNode].isFree = false; 70 if (pos == 0) // 如果添加的元素在第1个 71 { 72 node[freeNode].next = head; 73 head = freeNode; 74 } 75 else // 其他 76 { 77 int ptr = head; 78 int count = 0; 79 while (ptr != NULL_VALUE && count < pos - 1) 80 { 81 ptr = node[ptr].next; 82 count++; 83 } 84 node[freeNode].next = node[ptr].next; 85 node[ptr].next = freeNode; 86 } 87 } 88 } 89 return success; 90 } 91 92 bool LinkedList::deleteNode(const int pos) 93 { 94 bool success = true; 95 int len = getLenOfList(); 96 if (len == 0) 97 { 98 cerr << "There is no element in the list." << endl; 99 success = false; 100 } 101 else 102 { 103 int ptr = head, tmpPtr; 104 int count = 0; 105 // assert(0 <= pos <= len); 106 if (pos < 0 || pos > len - 1) 107 { 108 cerr << "The node at position " << pos << " you want to delete is less than zero or larger than " 109 << "the length of list ." << endl; 110 success = false; 111 throw out_of_range("out_of_range"); 112 } 113 else if (pos == 0) // 在链表第一个位置 114 { 115 head = node[head].next; 116 node[ptr].data = 0; 117 node[ptr].next = NULL_VALUE; 118 node[ptr].isFree = true; 119 } 120 else if (pos == len - 1) // 在链表最后一个位置 121 { 122 while (ptr != NULL && count < pos - 1) 123 { 124 ptr = node[ptr].next; 125 count++; 126 } 127 tmpPtr = node[ptr].next; 128 node[ptr].next = NULL_VALUE; 129 // reset the deleted one 130 node[tmpPtr].data = 0; 131 node[tmpPtr].next = NULL_VALUE; 132 node[tmpPtr].isFree = true; 133 } 134 else // 其他 135 { 136 while (ptr != NULL && count < pos - 1) 137 { 138 ptr = node[ptr].next; 139 count++; 140 } 141 tmpPtr = node[ptr].next; 142 node[ptr].next = node[tmpPtr].next; 143 // reset the deleted one 144 node[tmpPtr].data = 0; 145 node[tmpPtr].next = NULL_VALUE; 146 node[tmpPtr].isFree = true; 147 } 148 } 149 return success; 150 } 151 152 void LinkedList::displayNodes() 153 { 154 int ptr = head; 155 int sequence = 0; 156 while (ptr != NULL_VALUE) 157 { 158 cout << "Seq: " << sequence << "; Data: " << node[ptr].data << endl; 159 ptr = node[ptr].next; 160 sequence++; 161 } 162 } 163 164 NodeType LinkedList::getNode(const int pos) 165 { 166 NodeType tmpNode; 167 int len = getLenOfList(); 168 if (len == 0) 169 { 170 cerr << "There is no element in the list." << endl; 171 } 172 else 173 { 174 // assert(0 <= pos <= len); 175 if (pos < 0 || pos > len - 1) 176 { 177 cerr << "The item at position " << pos << " you want to get is less than zero or " 178 << "larger than the length of list." << endl; 179 throw out_of_range("out_of_range"); 180 // return tmpNode; 181 } 182 else 183 { 184 int ptr = head; 185 int count = 0; 186 while (ptr != NULL_VALUE && count < pos) 187 { 188 ptr = node[ptr].next; 189 count++; 190 } 191 tmpNode.data = node[ptr].data; 192 tmpNode.next = node[ptr].next; 193 tmpNode.isFree = node[ptr].isFree; 194 } 195 } 196 197 return tmpNode; 198 } 199 200 int LinkedList::getLenOfList() 201 { 202 int ptr = head; 203 int len = 0; 204 while (ptr != NULL_VALUE) 205 { 206 ptr = node[ptr].next; 207 len++; 208 } 209 210 return len; 211 }
Boost单元测试代码测试如下:
1 #define BOOST_TEST_MODULE LinkedList_Test_Module 2 3 #include "stdafx.h" 4 #include "D:VSProjectAlgorithmListLinkedListSingleLinkedList_BasedOnArraySingleLinkedListSingleLinkedListlinkedlist.h" 5 6 struct LinkedList_Fixture 7 { 8 public: 9 LinkedList_Fixture() 10 { 11 testLinkedList = new LinkedList(); 12 } 13 ~LinkedList_Fixture() 14 { 15 delete testLinkedList; 16 } 17 18 LinkedList * testLinkedList; 19 }; 20 21 BOOST_FIXTURE_TEST_SUITE(LinkedList_Test_Suite, LinkedList_Fixture) 22 23 24 BOOST_AUTO_TEST_CASE( LinkedList_Normal_Test ) 25 { 26 // isEmpty ------------------------------------------- 27 BOOST_REQUIRE(testLinkedList->isEmpty() == true); 28 29 // getLenOfList -------------------------------------- 30 BOOST_REQUIRE(testLinkedList->getLenOfList() == 0); 31 32 // findFreeNode -------------------------------------- 33 BOOST_REQUIRE(testLinkedList->findFreeNode() == 0); 34 35 // addNode & getNode --------------------------------- 36 BOOST_REQUIRE(testLinkedList->addNode(0, 0) == true); 37 BOOST_REQUIRE((testLinkedList->getNode(0)).data == 0); 38 BOOST_REQUIRE((testLinkedList->getNode(0)).next == NULL_VALUE); 39 BOOST_REQUIRE((testLinkedList->getNode(0)).isFree == false); 40 BOOST_REQUIRE(testLinkedList->isEmpty() == false); 41 BOOST_REQUIRE(testLinkedList->getLenOfList() == 1); 42 43 BOOST_REQUIRE(testLinkedList->addNode(1, 2) == true); 44 BOOST_REQUIRE((testLinkedList->getNode(1)).data == 2); 45 BOOST_REQUIRE((testLinkedList->getNode(1)).next == NULL_VALUE); 46 BOOST_REQUIRE((testLinkedList->getNode(1)).isFree == false); 47 BOOST_REQUIRE(testLinkedList->isEmpty() == false); 48 BOOST_REQUIRE(testLinkedList->getLenOfList() == 2); 49 50 BOOST_REQUIRE(testLinkedList->addNode(1, 1) == true); 51 BOOST_REQUIRE((testLinkedList->getNode(1)).data == 1); 52 BOOST_REQUIRE((testLinkedList->getNode(1)).next != NULL_VALUE); 53 BOOST_REQUIRE((testLinkedList->getNode(1)).isFree == false); 54 BOOST_REQUIRE((testLinkedList->getNode(2)).next == NULL_VALUE); 55 BOOST_REQUIRE(testLinkedList->isEmpty() == false); 56 BOOST_REQUIRE(testLinkedList->getLenOfList() == 3); 57 58 // deleteNode ----------------------------------------- 59 BOOST_REQUIRE(testLinkedList->deleteNode(0) == true); 60 BOOST_REQUIRE((testLinkedList->getNode(0)).data == 1); 61 BOOST_REQUIRE(testLinkedList->getLenOfList() == 2); 62 63 BOOST_REQUIRE(testLinkedList->deleteNode(1) == true); 64 BOOST_REQUIRE((testLinkedList->getNode(0)).data == 1); 65 BOOST_REQUIRE(testLinkedList->getLenOfList() == 1); 66 67 BOOST_REQUIRE(testLinkedList->deleteNode(0) == true); 68 BOOST_REQUIRE(testLinkedList->getLenOfList() == 0); 69 70 // initList ------------------------------------------- 71 int arr[] = { 0, 1, 2 }; 72 int len = sizeof(arr) / sizeof(int); 73 testLinkedList->initList(arr, len); 74 BOOST_REQUIRE(testLinkedList->getLenOfList() == 3); 75 BOOST_REQUIRE((testLinkedList->getNode(0)).data == 0); 76 BOOST_REQUIRE((testLinkedList->getNode(0)).next == 1); 77 78 BOOST_REQUIRE((testLinkedList->getNode(1)).data == 1); 79 BOOST_REQUIRE((testLinkedList->getNode(1)).next == 2); 80 81 BOOST_REQUIRE((testLinkedList->getNode(2)).data == 2); 82 BOOST_REQUIRE((testLinkedList->getNode(2)).next == NULL_VALUE); 83 } 84 85 BOOST_AUTO_TEST_CASE(LinkedList_Abnormal_Test) 86 { 87 int arr[] = { 0, 1, 2 }; 88 int len = sizeof(arr) / sizeof(int); 89 testLinkedList->initList(arr, len); 90 91 // addNode ------------------------------------------- 92 BOOST_REQUIRE_THROW(testLinkedList->addNode(-1, 100), out_of_range); 93 BOOST_REQUIRE_THROW(testLinkedList->addNode(10, 100), out_of_range); 94 95 // deleteNode ---------------------------------------- 96 BOOST_REQUIRE_THROW(testLinkedList->deleteNode(-1), out_of_range); 97 BOOST_REQUIRE_THROW(testLinkedList->deleteNode(10), out_of_range); 98 99 // getNode -------------------------------------------- 100 BOOST_REQUIRE_THROW(testLinkedList->getNode(-1), out_of_range); 101 BOOST_REQUIRE_THROW(testLinkedList->getNode(10), out_of_range); 102 103 } 104 105 106 BOOST_AUTO_TEST_SUITE_END()
本篇博文的代码均托管到Taocode : http://code.taobao.org/p/datastructureandalgorithm/src/.