zoukankan      html  css  js  c++  java
  • "《算法导论》之‘线性表’":基于数组实现的单链表

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

      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: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()
    BoostUnitTest.cpp

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

  • 相关阅读:
    敏捷开发系列学习总结(5)——这几招搞定团队协同Coding
    敏捷开发系列学习总结(4)—Git管理工具sourcetree的安装
    Java基础学习总结(74)——Java常见笔试题及答案汇总
    iOS 极光推送
    iOS UI控件没有显示时的调试技巧
    iOS 搜索之拼音搜索
    iOS MJExtension框架之字典数组转模型数组
    iOS 单例
    iOS 切换键盘
    iOS 正则表达式
  • 原文地址:https://www.cnblogs.com/xiehongfeng100/p/4054948.html
Copyright © 2011-2022 走看看