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


      对于单链表的介绍部分参考自博文数组、单链表和双链表介绍 以及 双向链表的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 }
    linkedlist.cpp

      Boost单元测试代码如下:

      1 // BoostUnitTest.cpp
      2 #define BOOST_TEST_MODULE LinkedList_Test_Module
      3 
      4 #include "stdafx.h"
      5 #include "D:VSProjectAlgorithmListLinkedListSingleLinkedList_BasedOnPointerSingleLinkedListSingleLinkedListlinkedlist.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()
    BoostUnitTest.cpp

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

  • 相关阅读:
    mybatis0206 延迟加载
    怎样关闭“粘滞键”?
    TNS-12557: TNS:protocol adapter not loadable TNS-12560: TNS:protocol adapter error
    HTTP协议头部与Keep-Alive模式详解
    oracle定时器执行一遍就不执行或本就不执行
    Inflation System Properties
    https://stackoverflow.com/questions/16130292/java-lang-outofmemoryerror-permgen-space-java-reflection
    java spring中对properties属性文件加密及其解密
    annotation配置springMVC的方法了事务不起作用
    SQLPlus在连接时通常有四种方式
  • 原文地址:https://www.cnblogs.com/xiehongfeng100/p/4052994.html
Copyright © 2020-2023  润新知