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

  对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表)。现在我们就来看看怎么用数组来实现单链表。

  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;
linkedlist.h
  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 }
linkedlist.cpp

  Boost单元测试代码测试如下:

  1 #define BOOST_TEST_MODULE LinkedList_Test_Module
  2 
  3 #include "stdafx.h"
  4 #include "D:\VSProject\Algorithm\List\LinkedList\SingleLinkedList_BasedOnArray\SingleLinkedList\SingleLinkedList\linkedlist.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()
BoostUnitTest.cpp

 

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

 

posted @ 2014-10-27 19:32  峰子_仰望阳光  阅读(728)  评论(0编辑  收藏  举报