• C++ 学习系列 -- std::list


    一  std::list 介绍

           list 是 c++ 中的序列式容器,其实现是双向链表,每个元素都有两个指针,分别指向前一个节点与后一个节点

          链表与数组都是计算机常用的内存数据结构,与数组连续内存空间不一样的地方在于,链表的空间是不连续的,链表是将一块块不连续的内存串联起来使用。

        正是由于链表的内存不连续这一特点,所以不能像数组一样,可以根据位置随机的访问每个元素,而链表我们压根不知道每个元素的实际位置到底在哪块内存区域。

         查找某个元素需要遍历整个链表,直到找到目标元素位置,时间复杂度是 O(n);

        在链表中插入一个元素与删除一个元素的时间复杂度是 O(1);

    二   c++ 中 stl 链表结构

    1. list 结构

       list  结构 (借用侯捷老师的一张图片来):

      

      由上面的结构上可以看出,list 是一个循环链表,链表的尾端是一个空节点,不存储任何数据。

    三   c++ 中 stl 链表使用

     1  构造函数

    构造函数说明
    list()空构造函数
    list( size_type count, const T& value)初始化一个元素数量为 count 个的 value 元素
    list( std::initializer_list init)利用列表初始化 list
    list( InputIt first, InputIt last)利用迭代器的起始于终止位置初始化 list

     2   容器修改

    函数说明
    clear() 清空所有元素
    insert在指定位置插入元素
    emplace在指定位置插入元素, 可以通过直接传入元素类的构造参数实现原地构造
    erase移除指定元素
    push_backappend 元素到链表的尾部
    pop_back将链表尾部元素弹出
    push_frontappend 元素到链表的头部
    pop_front将链表头部元素弹出
    emplace_backappend 元素到链表的尾部, 可以通过直接传入元素类的构造参数实现原地构造
    emplace_frontappend 元素到链表的头部, 可以通过直接传入元素类的构造参数实现原地构造

     3  容器访问

    函数说明
    begin返回头部元素的迭代器
    end返回尾部元素的迭代器
    rbegin返回尾部元素的迭代器
    rend返回头部元素的迭代器
    front返回头部元素的引用
    back返回尾部元素的引用

    4  容器容量

    函数说明
    empty判断 list是否为空
    size返回 list 存储元素的个数
    1. #include
    2. #include
    3. int main()
    4. {
    5. // 1. 构造函数
    6. std::list<int> list;
    7. auto iter = list.begin();
    8. std::cout << *iter << "--- " << std::endl;;
    9. // 2. 容器修改
    10. list.push_back(1);
    11. list.push_back(2);
    12. list.push_back(3);
    13. list.push_back(4);
    14. list.push_back(5);
    15. list.push_front(11);
    16. list.push_front(22);
    17. list.pop_back();
    18. list.pop_front();
    19. list.insert(list.begin(), 666);
    20. // 3. 容器访问
    21. for(auto iter = list.begin(); iter != list.end();iter++)
    22. {
    23. std::cout << *iter << " "; // 666 11 1 2 3 4
    24. }
    25. std::cout << "" << std::endl;
    26. for(auto iter = list.rbegin(); iter != list.rend();iter++)
    27. {
    28. std::cout << *iter << " "; // 4 3 2 1 11 666
    29. }
    30. std::cout << "" << std::endl;
    31. std::cout << "first: " << list.front() << ", finish: " << list.back() << std::endl; // first: 666, finish: 4
    32. // 4. 容器容量
    33. std::cout << "empyt: " << list.empty() << std::endl; // 0
    34. std::cout << "size: "<< list.size() << std::endl; // 6
    35. list.clear();
    36. std::cout << "empyt: " << list.empty() << std::endl; // 1
    37. std::cout << "size: "<< list.size() << std::endl; // 0
    38. return 0;
    39. }

    四  简单实现

      

    1. // my_list.h
    2. #include
    3. #include
    4. template<typename T>
    5. struct _List_Node
    6. {
    7. typedef _List_Node node;
    8. _List_Node()
    9. {
    10. prev = nullptr;
    11. next = nullptr;
    12. }
    13. _List_Node(T& da):data(da)
    14. {
    15. prev = nullptr;
    16. next = nullptr;
    17. }
    18. _List_Node(T&& da):data(da)
    19. {
    20. prev = nullptr;
    21. next = nullptr;
    22. }
    23. ~_List_Node()
    24. {
    25. prev = nullptr;
    26. next = nullptr;
    27. }
    28. node* prev;
    29. node* next;
    30. T data;
    31. };
    32. template<typename T>
    33. struct _List_Iterator
    34. {
    35. typedef T valueType;
    36. typedef T& refrence;
    37. typedef T* pointer;
    38. typedef _List_Node node;
    39. _List_Iterator(node* val):data(val)
    40. {
    41. }
    42. _List_Iterator& operator++()
    43. {
    44. this->data = this->data->next;
    45. return *this;
    46. }
    47. _List_Iterator operator++(int)
    48. {
    49. _List_Iterator tmp = *this;
    50. ++(*this);
    51. return tmp;
    52. }
    53. _List_Iterator& operator--()
    54. {
    55. this->data = this->data->prev;
    56. return *this;
    57. }
    58. _List_Iterator operator--(int)
    59. {
    60. _List_Iterator tmp = *this;
    61. --(*this);
    62. return tmp;
    63. }
    64. T& operator*()
    65. {
    66. return this->data->data;
    67. }
    68. bool operator != (_List_Iterator& other)
    69. {
    70. return this->data != other->data;
    71. }
    72. bool operator == (_List_Iterator& other)
    73. {
    74. return this->data == other.data;
    75. }
    76. bool operator != (_List_Iterator&& other)
    77. {
    78. return this->data != other.data;
    79. }
    80. bool operator == (_List_Iterator&& other)
    81. {
    82. return this->data == other.data;
    83. }
    84. node* data;
    85. };
    86. template<typename T>
    87. class my_list
    88. {
    89. typedef _List_Node node;
    90. typedef _List_Iterator iterator;
    91. public:
    92. my_list():count(0)
    93. {
    94. next_curr = new node;
    95. pre_curr = next_curr;
    96. finish = new node;
    97. next_curr->next = finish;
    98. finish->next = next_curr;
    99. pre_curr->prev = finish;
    100. finish->prev = pre_curr;
    101. }
    102. ~my_list()
    103. {
    104. node* tmp = pre_curr;
    105. while (tmp != nullptr) {
    106. node* tt = tmp->next;
    107. delete tmp;
    108. tmp = tt;
    109. }
    110. }
    111. void push_back(T& val)
    112. {
    113. std::cout << "count: " << count << std::endl;
    114. if(count == 0)
    115. next_curr->data = val;
    116. else {
    117. node* tmp = new node(val);
    118. tmp->next = next_curr->next;
    119. tmp->next->prev = tmp;
    120. next_curr->next = tmp;
    121. tmp->prev = next_curr;
    122. next_curr = next_curr->next;
    123. }
    124. count++;
    125. }
    126. void push_back(T&& val)
    127. {
    128. push_back(val);
    129. }
    130. void push_front(T& val)
    131. {
    132. if(count == 0)
    133. pre_curr->data = val;
    134. else {
    135. node* tmp = new node(val);
    136. tmp->prev = pre_curr->prev;
    137. pre_curr->prev->next = tmp;
    138. tmp->next = pre_curr;
    139. pre_curr->prev = tmp;
    140. pre_curr = pre_curr->prev;
    141. }
    142. count++;
    143. }
    144. void push_front(T&& val)
    145. {
    146. push_front(val);
    147. }
    148. void pop_back()
    149. {
    150. if(count == 0)
    151. {
    152. return;
    153. } else
    154. {
    155. node* tmp = next_curr;
    156. next_curr->prev->next = next_curr->next;
    157. next_curr->next->prev = next_curr->prev;
    158. next_curr = next_curr->prev;
    159. delete tmp;
    160. count--;
    161. }
    162. }
    163. void pop_front()
    164. {
    165. if(count == 0)
    166. {
    167. return;
    168. } else
    169. {
    170. node* tmp = pre_curr;
    171. finish->next = pre_curr->next;
    172. pre_curr->next->prev = finish;
    173. pre_curr = pre_curr->next;
    174. delete tmp;
    175. count--;
    176. }
    177. }
    178. int size()
    179. {
    180. return count;
    181. }
    182. iterator begin()
    183. {
    184. return iterator(pre_curr);
    185. }
    186. iterator end()
    187. {
    188. return iterator(finish);
    189. }
    190. iterator rbegin()
    191. {
    192. return iterator(finish->prev);
    193. }
    194. iterator rend()
    195. {
    196. return iterator(pre_curr->prev);
    197. }
    198. void insert(iterator pos, T& val)
    199. {
    200. node* tmp = new node(val);
    201. pos.data->prev->next = tmp;
    202. tmp->prev = pos.data->prev;
    203. tmp->next = pos.data;
    204. pos.data->prev = tmp;
    205. if(pos.data == pre_curr)
    206. {
    207. pre_curr = pre_curr->prev;
    208. }
    209. else if(pos.data == next_curr){
    210. next_curr = next_curr->next;
    211. }
    212. count++;
    213. }
    214. void insert(iterator pos, T&& val)
    215. {
    216. insert(pos, val);
    217. }
    218. template<typename ... Args>
    219. void emplace(iterator pos, Args... args)
    220. {
    221. node* tmp = new node(std::forward(args)...);
    222. pos.data->prev->next = tmp;
    223. tmp->prev = pos.data->prev->next;
    224. tmp->next = pos.data;
    225. pos.data->prev = tmp;
    226. count++;
    227. }
    228. void erase(iterator pos)
    229. {
    230. node* tmp = pos.data;
    231. tmp->prev = tmp->next;
    232. delete tmp;
    233. count--;
    234. }
    235. void clear()
    236. {
    237. while (pre_curr->next != finish) {
    238. pop_back();
    239. }
    240. count = 0;
    241. }
    242. T& front()
    243. {
    244. return pre_curr->data;
    245. }
    246. T& back()
    247. {
    248. return next_curr->data;
    249. }
    250. bool empty()
    251. {
    252. return count == 0;
    253. }
    254. public:
    255. node* next_curr = nullptr;
    256. node* pre_curr = nullptr;
    257. node* finish = nullptr;
    258. int count;
    259. };
    260. // main.cpp
    261. #include
    262. #include
    263. int main()
    264. {
    265. // 1. 构造函数
    266. my_list<int> list;
    267. // 2. 容器修改
    268. list.push_back(1);
    269. list.push_back(2);
    270. list.push_back(3);
    271. list.push_back(4);
    272. list.push_back(5);
    273. list.push_front(11);
    274. list.push_front(22);
    275. // 22 11 1 2 3 4 5
    276. list.pop_back();
    277. list.pop_front();
    278. list.insert(list.begin(), 666);
    279. // 3. 容器访问
    280. for(auto iter = list.begin(); iter != list.end();iter++)
    281. {
    282. std::cout << *iter << " "; // 666 11 1 2 3 4
    283. }
    284. std::cout << "" << std::endl;
    285. for(auto iter = list.rbegin(); iter != list.rend();iter--)
    286. {
    287. std::cout << *iter << " "; // 4 3 2 1 11 666
    288. }
    289. std::cout << "" << std::endl;
    290. std::cout << "first: " << list.front() << ", finish: " << list.back() << std::endl; // first: 666, finish: 4
    291. // 3. 容器容量
    292. std::cout << "empty: " << list.empty() << std::endl; // 0
    293. std::cout << "size: "<< list.size() << std::endl; // 6
    294. list.clear();
    295. std::cout << "empyt: " << list.empty() << std::endl; // 1
    296. std::cout << "size: "<< list.size() << std::endl; // 0
    297. return 0;
    298. }

  • 相关阅读:
    STM32-- GPIO->EXTI->NVIC中断
    Java爬虫实战系列——常用的Java网络爬虫库
    React源码分析(二)渲染机制
    第10集丨龙场悟道:阳明心学的诞生
    css实现日出日落效果
    python软件许可License文件生成
    【go】报错整理与解决
    MPEG 解封装
    Redis——认识Redis
    node实现basic认证 及fs模块读取html,进行路由跳转
  • 原文地址:https://blog.csdn.net/qq_33775774/article/details/133589986