首页 > 代码库 > 基于数组实现的单链表(兼具Boost单元测试)

基于数组实现的单链表(兼具Boost单元测试)

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

  1. 定义单链表中结点的数据结构

1 typedef int ElementType;2 class NodeType3 {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 = http://www.mamicode.com/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 = http://www.mamicode.com/-1;10 11 typedef int ElementType;12 class NodeType13 {14 public:15     NodeType() { data = http://www.mamicode.com/0;  next = NULL_VALUE; isFree = true; };16     ~NodeType() {};17     ElementType data;18     int next;19     bool isFree;    // 标志位,为true表示该结点可用,反之不可用20 };21 22 class LinkedList23 {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 = http://www.mamicode.com/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 =http://www.mamicode.com/ 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     else102     {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 = http://www.mamicode.com/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 one130             node[tmpPtr].data = http://www.mamicode.com/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 one144             node[tmpPtr].data = http://www.mamicode.com/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     else173     {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         else183         {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 =http://www.mamicode.com/ 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 =http://www.mamicode.com/= 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 =http://www.mamicode.com/= 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 =http://www.mamicode.com/= 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 =http://www.mamicode.com/= 1); 61     BOOST_REQUIRE(testLinkedList->getLenOfList() == 2); 62  63     BOOST_REQUIRE(testLinkedList->deleteNode(1) == true); 64     BOOST_REQUIRE((testLinkedList->getNode(0)).data =http://www.mamicode.com/= 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 =http://www.mamicode.com/= 0); 76     BOOST_REQUIRE((testLinkedList->getNode(0)).next == 1); 77  78     BOOST_REQUIRE((testLinkedList->getNode(1)).data =http://www.mamicode.com/= 1); 79     BOOST_REQUIRE((testLinkedList->getNode(1)).next == 2); 80  81     BOOST_REQUIRE((testLinkedList->getNode(2)).data =http://www.mamicode.com/= 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

 

  个人“数据结构与算法”系列博文:

  线性表:

    顺序表:

      基于静态分配的数组的顺序表(兼具Boost单元测试)

      基于动态分配的数组的顺序表(兼具Boost单元测试)

    链表:

      基于指针实现的单链表(兼具Boost单元测试)

      基于数组实现的单链表(兼具Boost单元测试)

 

基于数组实现的单链表(兼具Boost单元测试)