• C++ 手动实现双向链表(作业版)


    双向链表,并实现增删查改等功能

    首先定义节点类,类成员包含当前节点的值, 指向下一个节点的指针和指向上一个节点的指针

    1. //节点定义
    2. template <typename T>
    3. class Node {
    4. public:
    5. Node* prior;
    6. T value;
    7. Node* next;
    8. Node():value(0),prior(nullptr),next(nullptr) {}
    9. Node(T n):prior(nullptr),value(n),next(nullptr) {}
    10. };

    然后是链表类的定义,主要包含了增删查改等功能

    1. //双向链表定义
    2. template <typename T>
    3. class LinkList_doubly {
    4. public:
    5. Node* firstNode;
    6. Node* lastNode;
    7. LinkList_doubly();
    8. LinkList_doubly(int n, const T* arr);
    9. LinkList_doubly(const LinkList_doubly& link);
    10. ~LinkList_doubly();
    11. LinkList_doubly& push_back(T n);
    12. LinkList_doubly& push_front(T n);
    13. LinkList_doubly& insert(int pos, int n, T* arr);
    14. LinkList_doubly& pop_front();
    15. LinkList_doubly& pop_back();
    16. LinkList_doubly& remove(int pos, int num);
    17. LinkList_doubly& reverse();
    18. T& operator[](int n);
    19. T& at(int n);
    20. LinkList_doubly& replace(int pos, int n, T* arr);
    21. int getLen() {return len;}
    22. void clear() {this->~LinkList_doubly();}
    23. void display();
    24. private:
    25. int len = 0;
    26. Node* getNode_next(int n);
    27. };

    各个函数解释:

    LinkList_doubly();      默认构造函数

    LinkList_doubly(const T* arr, int len);      一般构造函数

    LinkList_doubly(const LinkList& link)           拷贝构造函数

    ~LinkList_doubly();     析构函数

    LinkList_doubly& push_back(T n);    在尾部添加一个元素

    LinkList_doubly& push_front(T n);     在头部添加一个元素

    LinkList_doubly& insert(int pos, int n, T* arr);   在pos处插入n个元素

    LinkList_doubly& pop_front();    删除第一个节点

    LinkList_doubly& pop_back();    删除最后一个节点

    LinkList_doubly& remove(int pos, int num);     删除pos开始的num个元素

    LinkList_doubly& reverse();     反转链表

    T& operator[](int n);     重载[ ]运算符,返回第n个节点的值

    T& at(int n);                 与[ ]一样,只不过会检查索引是否越界

    LinkList_doubly& replace(int pos, int n, T* arr);    替换n个节点

    int getLen() {return len;}     返回长度,因为len是private

    void clear() {this->~LinkList();}    清除链表

    void display();    显示链表所有元素

    Node* getNode_next(int n);     返回第n个节点的next指针

    1. #include
    2. using namespace std;
    3. template <typename T>
    4. class Node {
    5. public:
    6. Node* prior;
    7. T value;
    8. Node* next;
    9. Node():value(0),prior(nullptr),next(nullptr) {}
    10. Node(T n):prior(nullptr),value(n),next(nullptr) {}
    11. };
    12. template <typename T>
    13. class LinkList_doubly {
    14. public:
    15. Node* firstNode;
    16. Node* lastNode;
    17. LinkList_doubly();
    18. LinkList_doubly(int n, const T* arr);
    19. LinkList_doubly(const LinkList_doubly& link);
    20. ~LinkList_doubly();
    21. LinkList_doubly& push_back(T n);
    22. LinkList_doubly& push_front(T n);
    23. LinkList_doubly& insert(int pos, int n, T* arr);
    24. LinkList_doubly& pop_front();
    25. LinkList_doubly& pop_back();
    26. LinkList_doubly& remove(int pos, int num);
    27. LinkList_doubly& reverse();
    28. T& operator[](int n);
    29. T& at(int n);
    30. LinkList_doubly& replace(int pos, int n, T* arr);
    31. int getLen() {return len;}
    32. void clear() {this->~LinkList_doubly();}
    33. void display();
    34. private:
    35. int len = 0;
    36. Node* getNode_next(int n);
    37. };
    38. //默认构造函数
    39. template <typename T>
    40. LinkList_doubly::LinkList_doubly() {
    41. firstNode = nullptr;
    42. lastNode = nullptr;
    43. len = 0;
    44. }
    45. //一般构造函数,用数组进行初始化
    46. template <typename T>
    47. LinkList_doubly::LinkList_doubly(int n, const T* arr) {
    48. Node* temp1 = nullptr;
    49. Node* temp2 = nullptr;
    50. for (int i = 0; i < n; i++) {
    51. temp1 = new Node (arr[i]);
    52. if ( i == 0 )
    53. firstNode = temp1;
    54. if ( i == n-1 )
    55. lastNode = temp1;
    56. temp1->prior = temp2;
    57. if ( i > 0 )
    58. temp2->next = temp1;
    59. temp2 = temp1;
    60. }
    61. this->len = n;
    62. }
    63. //拷贝构造函数
    64. template <typename T>
    65. LinkList_doubly::LinkList_doubly(const LinkList_doubly& link) {
    66. this->firstNode = link.firstNode;
    67. this->lastNode = link.lastNode;
    68. this->len = link.getLen();
    69. }
    70. //析构函数
    71. template <typename T>
    72. LinkList_doubly::~LinkList_doubly() {
    73. this->len = 0;
    74. Node* temp = firstNode;
    75. lastNode = nullptr;
    76. while ( firstNode ) {
    77. temp = firstNode;
    78. firstNode = firstNode->next;
    79. delete temp;
    80. temp = nullptr;
    81. }
    82. }
    83. //在尾部添加一个元素
    84. template <typename T>
    85. LinkList_doubly& LinkList_doubly::push_back(T n) {
    86. Node* newNode = new Node (n);
    87. newNode->prior = lastNode;
    88. lastNode->next = newNode;
    89. lastNode = newNode;
    90. len++;
    91. return *this;
    92. }
    93. //在头部添加一个元素
    94. template <typename T>
    95. LinkList_doubly& LinkList_doubly::push_front(T n) {
    96. Node* newNode = new Node (n);
    97. newNode->next = firstNode;
    98. firstNode->prior = newNode;
    99. firstNode = newNode;
    100. len++;
    101. return *this;
    102. }
    103. //在position位置插入n个元素
    104. template <typename T>
    105. LinkList_doubly& LinkList_doubly::insert(int pos, int n, T* arr) {
    106. if ( pos < 0 || pos > len-1 ) {
    107. cout << "[error]: illegal insert index, please check" << endl;
    108. exit(0);
    109. }
    110. if ( pos == 0 ) {
    111. for ( int i = 0; i < n; i++ )
    112. this->push_front(arr[n-1-i]); //push_front自带len++
    113. return *this;
    114. }
    115. Node* temp_end = getNode_next(pos);
    116. Node* temp_front = getNode_next(pos-1);
    117. Node* temp_new = nullptr;
    118. for ( int i = 0; i < n; i++ ) {
    119. temp_new = new Node (arr[i]);
    120. temp_front->next = temp_new;
    121. temp_new->prior = temp_front;
    122. temp_front = temp_front->next;
    123. }
    124. temp_front->next = temp_end;
    125. temp_end->prior = temp_front;
    126. len += n;
    127. return *this;
    128. }
    129. //删除第一个元素
    130. template <typename T>
    131. LinkList_doubly& LinkList_doubly::pop_front() {
    132. if ( len == 0 ) {
    133. cout << "[warning]: linkedlist is empty" << endl;
    134. return *this;
    135. }
    136. Node* temp = firstNode;
    137. firstNode = firstNode->next;
    138. firstNode->prior = nullptr;
    139. delete temp;
    140. len--;
    141. return *this;
    142. }
    143. //删除最后一个元素
    144. template <typename T>
    145. LinkList_doubly& LinkList_doubly::pop_back() {
    146. if ( len == 0 ) {
    147. cout << "[warning]: linkedlist is empty" << endl;
    148. return *this;
    149. }
    150. Node* temp = lastNode;
    151. lastNode = lastNode->prior;
    152. lastNode->next = nullptr;
    153. delete temp;
    154. len--;
    155. return *this;
    156. }
    157. //删除position开始的num个元素
    158. template <typename T>
    159. LinkList_doubly& LinkList_doubly::remove(int pos, int num) {
    160. if ( pos > len-1 || len < 0 || pos < 0 || pos > len-1) {
    161. cout << "[error]: illegal remove position, please check again" << endl;
    162. exit(0);
    163. } else if ( pos + num - 1 > len-1) {
    164. cout << "[error]: remove index out of range" << endl;
    165. exit(0);
    166. }
    167. //如果删除了首元节点或者尾节点,要考虑firstNode和lastNode的指向,用pop比较方便
    168. if ( pos == 0 ) {
    169. for ( int i = 0; i < num; i++ )
    170. this->pop_front();
    171. return *this;
    172. }
    173. if ( pos + num == len ) {
    174. for ( int i = 0; i < num; i++ )
    175. this->pop_back();
    176. return *this;
    177. }
    178. Node* temp_front = getNode_next(pos-1);
    179. Node* temp_end = getNode_next(pos+num);
    180. Node* temp = getNode_next(pos);
    181. while ( 1 ) {
    182. Node* node = temp;
    183. temp = temp->next;
    184. delete node;
    185. if ( temp == temp_end ) {
    186. break;
    187. }
    188. }
    189. temp_front->next = temp_end;
    190. temp_end->prior = temp_front;
    191. len -= num;
    192. return *this;
    193. }
    194. //替换元素
    195. template <typename T>
    196. LinkList_doubly& LinkList_doubly::replace(int pos, int n, T* arr) {
    197. Node* temp = getNode_next(pos);
    198. for ( int i = 0; i < n; i++ ) {
    199. temp->value = arr[i];
    200. temp = temp->next;
    201. }
    202. return *this;
    203. }
    204. //反转链表,终极偷懒写法,实在不想动脑子了
    205. template <typename T>
    206. LinkList_doubly& LinkList_doubly::reverse() {
    207. const int num = len;
    208. T arr[num];
    209. Node* temp = firstNode;
    210. for ( int i = 0; i < this->len; i++ ) {
    211. arr[i] = temp->value;
    212. temp = temp->next;
    213. }
    214. temp = lastNode;
    215. for ( int i = 0; i < this->len; i++ ) {
    216. temp->value = arr[i];
    217. temp = temp->prior;
    218. }
    219. return *this;
    220. }
    221. //访问第n个元素
    222. template <typename T>
    223. T& LinkList_doubly::operator[](int n){
    224. Node* temp = nullptr;
    225. if ( n <= len/2 ) {
    226. temp = firstNode;
    227. for ( int i = 0; i < n; i++ ) {
    228. temp = temp->next;
    229. }
    230. } else {
    231. temp = lastNode;
    232. for ( int i = 0; i < len-1-n; i++ ) {
    233. temp = temp->prior;
    234. }
    235. }
    236. return temp->value;
    237. }
    238. //访问第n个元素,增加索引检查
    239. template <typename T>
    240. T& LinkList_doubly::at(int n){
    241. if ( n < 0 || n > len-1 ) {
    242. cout << "[error]:index out of range" << endl;
    243. exit(0);
    244. }
    245. return (*this)[n];
    246. }
    247. //获取第n个Node的next指针
    248. template <typename T>
    249. Node* LinkList_doubly::getNode_next(int n) {
    250. if ( n > len-1 ) {
    251. cout << "[error]: illegal index" << endl;
    252. }
    253. Node* temp = firstNode;
    254. for ( int i = 0; i < n; i++ ) {
    255. temp = temp->next;
    256. }
    257. return temp;
    258. }
    259. //显示链表所有元素,会对链表正反向一致性进行检查
    260. template <typename T>
    261. void LinkList_doubly::display() {
    262. const int num = len;
    263. T arr1[num];
    264. T arr2[num];
    265. Node* temp = firstNode;
    266. for ( int i = 0; i < this->len; i++ ) {
    267. arr1[i] = temp->value;
    268. temp = temp->next;
    269. }
    270. temp = lastNode;
    271. for ( int i = 0; i < this->len; i++ ) {
    272. arr2[i] = temp->value;
    273. temp = temp->prior;
    274. }
    275. for ( int i = 0; i < this->len; i++ ) {
    276. if ( arr1[i] != arr2[len-1-i] ) {
    277. cout << "第"<"个元素正反向结果不一致" << arr1[i] << " " << arr2[len-1-i] << endl;
    278. exit(0);
    279. }
    280. }
    281. temp = firstNode;
    282. for ( int i = 0; i < this->len; i++ ) {
    283. cout << temp->value << " ";
    284. temp = temp->next;
    285. }
    286. cout << endl;
    287. }
    288. int main() {
    289. int arr[] = {1,5,7,3,5,3,1};
    290. LinkList_doubly<int> link(sizeof(arr)/sizeof(int), arr);
    291. link.display();
    292. link.push_back(25);
    293. link.display();
    294. link.push_front(10);
    295. link.display();
    296. int arr2[] = {1,0,0,4};
    297. link.insert(0,sizeof(arr2)/sizeof(int), arr2);
    298. link.display();
    299. link.pop_front();
    300. link.display();
    301. link.pop_back();
    302. link.display();
    303. link.remove(7,2);
    304. link.display();
    305. int arr3[] = {2,3,5};
    306. link.replace(4, sizeof(arr3)/sizeof(int), arr3);
    307. link.display();
    308. link.reverse();
    309. link.display();
    310. cout << link[8] << " " << link.at(3) << endl;
    311. cout << link.getLen() << endl;
    312. link.~LinkList_doubly();
    313. cout << link.getLen() << endl;
    314. }

  • 相关阅读:
    Windows内核--HAL在抽象什么?(3.4)
    Blender之锁定摄像机到视图方位
    连夜整理了多年后端开发最常用linux指令(建议收藏,边用边学)
    3.2python使用 matplotlib 实现可视化_python量化实用版教程(初级)
    这可能是2022年把微服务讲的最全了:SpringBoot+Cloud+Docker
    MSP432学习笔记7:定时器A中断
    Lumion和Enscape渲染器有什么区别?哪个适合你
    python开发环境搭建问题汇总
    携程OceanBase开源实践——索引统计功能实现
    【教3妹学算法-每日1题】竞赛题:矩阵中的局部最大值
  • 原文地址:https://blog.csdn.net/a1367666195/article/details/127988604