List容器学习

数据结构

List使用的数据结构为双向循环链表,使用node指针指向一个置于尾端的空白节点,node便是last迭代器,而node->next便是begin迭代器,形成“前闭后开”的区间。

迭代器

由于STL List为双向链表,故list提供的是双向迭代器(Bidirection Iterators),具备前后移功能。

List重要性质:Inset和splice操作不会造成原有的list的迭代器失效,这在vector中不成立,即使是erase操作都只失去指向被删节点的迭代器。

1.   template <class T>  

2.   struct __list_node  

3.   {  

4.       typedef void* void_pointer;  

5.       void_pointer next;  

6.       void_pointer prev;  

7.       T data;  

8.   };  

9.     

10. // 至于为什么不使用默认参数, 这个是因为有一些编译器不能提供推导能力,  

11. // 而作者又不想维护两份代码, 故不使用默认参数  

12. template<class T, class Ref, class Ptr>  

13. struct __list_iterator  

14. {  

15.     typedef __list_iterator<T, T&, T*>        iterator;   // STL标准强制要求  

16.     typedef __list_iterator<T, Ref, Ptr>      self;  

17.   

18.     typedef bidirectional_iterator_tag iterator_category;  

19.     typedef T value_type;  

20.     typedef Ptr pointer;  

21.     typedef Ref reference;  

22.     typedef __list_node<T>* link_type;  

23.     typedef size_t size_type;  

24.     typedef ptrdiff_t difference_type;  

25.   

26.     link_type node;   //迭代器内部当然要有一个普通指针,指向list的节点  

27.     

28.    //迭代器的三种构造方式

29.     __list_iterator(link_type x) : node(x) {}  //用链表,指向链表的Node节点

30.     __list_iterator() {}  

31.     __list_iterator(const iterator& x) : node(x.node) {}  //复制构造函数

32.   

33.     //重载

34.     // 在STL算法中需要迭代器提供支持  

35.     bool operator==(const self& x) const { return node == x.node; }  

36.     bool operator!=(const self& x) const { return node != x.node; }  

37.   

38.     // 以下对迭代器取值(dereference),取的是节点的数据值  

39.     reference operator*() const { return (*node).data; }  

40.   

41.     // 以下是迭代器的成员存取运算子的标准做法  

42.     pointer operator->() const { return &(operator*()); }  

43.   

44.     // 前缀自加,对迭代器累加1,就是前进一个节点  

45.     self& operator++()  

46.     {  

47.         node = (link_type)((*node).next);  

48.         return *this;  

49.     }  

50.   

51.     // 后缀自加, 需要先产生自身的一个副本, 然会再对自身操作, 最后返回副本  

52.     self operator++(int)  

53.     {  

54.         self tmp = *this;  

55.         ++*this;  

56.         return tmp;  

57.     }  

58.   

59.     // 前缀自减  

60.     self& operator--()  

61.     {  

62.         node = (link_type)((*node).prev);  

63.         return *this;  

64.     }  

65.   

66.     self operator--(int)  

67.     {  

68.         self tmp = *this;  

69.         --*this;  

70.         return tmp;  

71.     }  

72. };  

List的构造与内存管理

       List缺省使用alloc作为空间配置器,并据此另外定义了一个list_node_allocator为了更方便的以节点大小为配置单位

1.   // 默认allocator为alloc, 其具体使用版本请参照<stl_alloc.h>  

2.   template <class T, class Alloc = alloc>  

3.   class list  

4.   {  

5.   protected:  

6.       typedef void* void_pointer;  

7.       typedef __list_node<T> list_node;  

8.     

9.       // 专属之空间配置器,每次配置一个节点大小  

10.     typedef simple_alloc<list_node, Alloc> list_node_allocator;  

11.   

12. public:  

13.     typedef T value_type;  

14.     typedef value_type* pointer;  

15.     typedef value_type& reference;  

16.     typedef list_node* link_type;  

17.     typedef size_t size_type;  

18.     typedef ptrdiff_t difference_type;  

19.   

20.     typedef __list_iterator<T, T&, T*> iterator;  

21.   

22. protected:  

23.     link_type node ;     // 只要一个指针,便可表示整个环状双向链表  

24.     // 分配一个新结点, 注意这里并不进行构造,  

25.     // 构造交给全局的construct, 见<stl_stl_uninitialized.h>  

26.     link_type get_node() { return list_node_allocator::allocate(); }  

27.   

28.     // 释放指定结点, 不进行析构, 析构交给全局的destroy  

29.     void put_node(link_type p) { list_node_allocator::deallocate(p); }  

30.   

31.     // 产生(配置并构造)一个节点, 首先分配内存, 然后进行构造  

32.     // 注: commit or rollback  

33.     link_type create_node(const T& x)  

34.     {  

35.         link_type p = get_node();  

36.         construct(&p->data, x);  

37.         return p;  

38.     }  

39.   

40.     // 析构结点元素, 并释放内存  

41.     void destroy_node(link_type p)  

42.     {  

43.         destroy(&p->data);  

44.         put_node(p);  

45.     }  

46.   

47. protected:  

48.     // 用于空链表的建立  

49.     void empty_initialize()  

50.     {  

51.         node = get_node();   // 配置一个节点空间,令node指向它  

52.         node->next = node;   // 令node头尾都指向自己,不设元素值  

53.         node->prev = node;  

54.     }  

55.   

56.   // 创建值为value共n个结点的链表  

57.   // 注: commit or rollback  

58.     void fill_initialize(size_type n, const T& value)  

59.     {  

60.         empty_initialize();  

61.         __STL_TRY  

62.         {  

63.             // 此处插入操作时间复杂度O(1)  

64.             insert(begin(), n, value);  

65.         }  

66.         __STL_UNWIND(clear(); put_node(node));  

67.     }  

68.  

69.     

70.     // 在指定位置插入元素  

71.     

72.     //       insert(iterator position, const T& x)  

73.     //                       ↓  

74.     //       create_node(x)  

75.     //      p = get_node();-------->list_node_allocator::allocate();  

76.     //      construct(&p->data, x);  

77.     //                       ↓  

78.     //     tmp->next = position.node;  

79.     //     tmp->prev = position.node->prev;  

80.     //     (link_type(position.node->prev))->next = tmp;  

81.     //     position.node->prev = tmp;  

82.     

83.   

84.     iterator insert(iterator position, const T& x)  

85.     {  

86.         link_type tmp = create_node(x);   // 产生一个节点  

87.         // 调整双向指针,使tmp插入进去  

88.         tmp->next = position.node;  

89.         tmp->prev = position.node->prev;  

90.         (link_type(position.node->prev))->next = tmp;  

91.         position.node->prev = tmp;  

92.         return tmp;  

93.     }

  List元素操作

常用操作:

在链头插入、删除;

push_front(const T& x) pop_front()

在链尾插入、删除;

push_back(const T& x) pop_back() 

·删除指定结点;

erase(iterator first, iterator last)  

置空整条链;

clear()    

返回链长;

size()

结合;

// 将链表x移动到position所指位置之前 

splice(iterator position, list& x)

// 将链表中i指向的内容移动到position之前  

splice(iterator position, list&, iterator i)

// [first, last}元素移动到position之前  

splice(iterator position, list&, iterator first, iterator last)  

删除所有值为value的结点;

remove(const T& value);  

删除连续且相同的元素,只剩一个;

unique()

将x合并到*this上,两链表需要递增排序;

merge(list& x);  

颠倒整个链表;

reverse()

排序;

// 使用quick sort,主要操作使用merge 

sort()

 

1.     // 在链表前端插入结点  

2.     void push_front(const T& x) { insert(begin(), x); }  

3.     // 在链表最后插入结点  

4.     void push_back(const T& x) { insert(end(), x); }  

5.     

6.     // 移除迭代器position所指节点  

7.     iterator erase(iterator position)  

8.     {  

9.         link_type next_node = link_type(position.node->next);  

10.       link_type prev_node = link_type(position.node->prev);  

11.       prev_node->next = next_node;  

12.       next_node->prev = prev_node;  

13.       destroy_node(position.node);  

14.       return iterator(next_node);  

15.   }  

16.   

17.   // 擦除一个区间的结点, 详细解析见实现部分  

18.   iterator erase(iterator first, iterator last);  

19.   

20.   void resize(size_type new_size, const T& x);  

21.   void resize(size_type new_size) { resize(new_size, T()); }  

22.   void clear();  

23.   

24.   // 删除链表第一个结点  

25.   void pop_front() { erase(begin()); }  

26.   // 删除链表最后一个结点  

27.   void pop_back()  

28.   {  

29.       iterator tmp = end();  

30.       erase(--tmp);  

31.   }  

32.  

33.   //构造函数

34.   list(size_type n, const T& value) { fill_initialize(n, value); }  

35.   list(int n, const T& value) { fill_initialize(n, value); }  

36.   list(long n, const T& value) { fill_initialize(n, value); }  

37.   

38.   ~list()  

39.   {  

40.     // 释放所有结点  

41.     // 使用全局函数distance()进行计算, 时间复杂度O(n)  

42.   size_type size() const  

43.   {  

44.     size_type result = 0;  

45.     distance(begin(), end(), result);  

46.     return result;  

47.   }  

48.   clear();  

49.   {

50.   // 释放头结点  

51.   put_node(node);  

52.   }  

53.   

54.   list<T, Alloc>& operator=(const list<T, Alloc>& x);  

55.   

56. protected:  

57.   

58.       

59.     // 将[first, last)内的所有元素移动到position之前  

60.     // 如果last == position, 则相当于链表不变化, 不进行操作  

61.       

62.     // 初始状态  

63.     //                   first                             last  

64.     //                     ↓                                 ↓  

65.     //      --------   --------   --------     --------   --------   --------  

66.     //      | next |-->| next |-->| next |     | next |-->| next |-->| next |  

67.     //  ... --------   --------   -------- ... --------   --------   -------- ...  

68.     //      | prev |<--| prev |<--| prev |     | prev |<--| prev |<--| prev |  

69.     //      --------   --------   --------     --------   --------   --------  

70.     //  

71.     //                           position  

72.     //                               ↓  

73.     //      --------   --------   --------   --------   --------   --------  

74.     //      | next |-->| next |-->| next |-->| next |-->| next |-->| next |  

75.     //  ... --------   --------   --------   --------   --------   -------- ...  

76.     //      | prev |<--| prev |<--| prev |<--| prev |<--| prev |<--| prev |  

77.     //      --------   --------   --------   --------   --------   --------  

78.     //  

79.     // 操作完成后状态  

80.     //                           first  

81.     //                             |  

82.     //               --------------|--------------------------------------  

83.     //               | ------------|------------------------------------ |   last  

84.     //               | |           ↓                                   | |     ↓  

85.     //      -------- | |        --------   --------     --------       | |  --------   --------  

86.     //      | next |-- |  ----->| next |-->| next |     | next |-----  | -->| next |-->| next |  

87.     //  ... --------   |  |     --------   -------- ... --------    |  |    --------   -------- ...  

88.     //      | prev |<---  |  ---| prev |<--| prev |     | prev |<-- |  -----| prev |<--| prev |  

89.     //      --------      |  |  --------   --------     --------  | |       --------   --------  

90.     //                    |  |                                    | |  

91.     //                    |  ------                               | |  

92.     //                    ------- |  ------------------------------ |  

93.     //                          | |  |                              |  

94.     //                          | |  |  -----------------------------  

95.     //                          | |  |  |  

96.     //                          | |  |  |  position  

97.     //                          | |  |  |     ↓  

98.     //      --------   -------- | |  |  |  --------   --------   --------   --------  

99.     //      | next |-->| next |-- |  |  -->| next |-->| next |-->| next |-->| next |  

100.      //  ... --------   --------   |  |     --------   --------   --------   -------- ...  

101.      //      | prev |<--| prev |<---  ------| prev |<--| prev |<--| prev |<--| prev |  

102.      //      --------   --------            --------   --------   --------   --------  

103.        

104.      void transfer(iterator position, iterator first, iterator last)  

105.      {  

106.          if (position != last)   // 如果last == position, 则相当于链表不变化, 不进行操作  

107.          {  

108.              (*(link_type((*last.node).prev))).next = position.node;  

109.              (*(link_type((*first.node).prev))).next = last.node;  

110.              (*(link_type((*position.node).prev))).next = first.node;  

111.              link_type tmp = link_type((*position.node).prev);  

112.              (*position.node).prev = (*last.node).prev;  

113.              (*last.node).prev = (*first.node).prev;  

114.              (*first.node).prev = tmp;  

115.          }  

116.      }  

117.    

118.  public:  

119.      // 将链表x移动到position所指位置之前  

120.      void splice(iterator position, list& x)  

121.      {  

122.          if (!x.empty())  

123.              transfer(position, x.begin(), x.end());  

124.      }  

125.    

126.      // 将链表中i指向的内容移动到position之前  

127.      void splice(iterator position, list&, iterator i)  

128.      {  

129.          iterator j = i;  

130.          ++j;  

131.          if (position == i || position == j) return;  

132.          transfer(position, i, j);  

133.      }  

134.    

135.      // 将[first, last}元素移动到position之前  

136.      void splice(iterator position, list&, iterator first, iterator last)  

137.      {  

138.          if (first != last)  

139.              transfer(position, first, last);  

140.      }  

141.    

142.      void remove(const T& value);  

143.      void unique();  

144.      void merge(list& x);  

145.      void reverse();  

146.      void sort();  

147.    

148.  };  

149.    

150.  // 销毁所有结点, 将链表置空  

151.  template <class T, class Alloc>  

152.  void list<T, Alloc>::clear()  

153.  {  

154.    link_type cur = (link_type) node->next;  

155.    while (cur != node)  

156.    {  

157.      link_type tmp = cur;  

158.      cur = (link_type) cur->next;  

159.      destroy_node(tmp);  

160.    }  

161.    // 恢复node原始状态  

162.    node->next = node;  

163.    node->prev = node;  

164.  }  

165.    

166.  // 链表赋值操作  

167.  // 如果当前容器元素少于x容器, 则析构多余元素,  

168.  // 否则将调用insert插入x中剩余的元素  

169.  template <class T, class Alloc>  

170.  list<T, Alloc>& list<T, Alloc>::operator=(const list<T, Alloc>& x)  

171.  {  

172.    if (this != &x)  

173.    {  

174.      iterator first1 = begin();  

175.      iterator last1 = end();  

176.      const_iterator first2 = x.begin();  

177.      const_iterator last2 = x.end();  

178.      while (first1 != last1 && first2 != last2) *first1++ = *first2++;  

179.      if (first2 == last2)  

180.        erase(first1, last1);  

181.      else  

182.        insert(last1, first2, last2);  

183.    }  

184.    return *this;  

185.  }  

186.    

187.    

188.  // 移除容器内所有的相邻的重复结点  

189.  // 时间复杂度O(n)  

190.  // 用户自定义数据类型需要提供operator ==()重载  

191.  template <class T, class Alloc>  

192.  void list<T, Alloc>::unique()  

193.  {  

194.    iterator first = begin();  

195.    iterator last = end();  

196.    if (first == last) return;  

197.    iterator next = first;  

198.    while (++next != last)  

199.    {  

200.      if (*first == *next)  

201.        erase(next);  

202.      else  

203.        first = next;  

204.      next = first;  

205.    }  

206.  }  

207.    

208.  // 假设当前容器和x都已序, 保证两容器合并后仍然有序  

209.  template <class T, class Alloc>  

210.  void list<T, Alloc>::merge(list<T, Alloc>& x)  

211.  {  

212.    iterator first1 = begin();  

213.    iterator last1 = end();  

214.    iterator first2 = x.begin();  

215.    iterator last2 = x.end();  

216.    

217.    // 注意:前提是,两个lists都已经递增排序  

218.    while (first1 != last1 && first2 != last2)  

219.      if (*first2 < *first1)  

220.      {  

221.        iterator next = first2;  

222.        transfer(first1, first2, ++next);  

223.        first2 = next;  

224.      }  

225.      else  

226.        ++first1;  

227.    if (first2 != last2)  

228.        transfer(last1, first2, last2);  

229.  }  

230.  template <class T, class Alloc>

231.  void list<T, alloc>::reverse()

232.  {

233.      //一下判断,如果是空链表,或仅有一个元素,就不进行任何操作

234.      //使用size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢

235.      if (noode->next == node || link_type(node->next)->next== node)

236.          return;

237.      iterator first = begin();

238.      ++first;

239.      while (first != begin())

240.      {

241.          iterator old = first;

242.          ++first;

243.          transfer(begin(),old, first);

244.      }

245.  }

246.   //本函数使用 quick sort

247.  template <class T, class Alloc>

248.  void list<T, alloc>::sort()

249.  {

250.      //一下判断,如果是空链表,或仅有一个元素,就不进行任何操作

251.      //使用size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢

252.      if (noode->next == node || link_type(node->next)->next== node)

253.          return;

254.   

255.      //一些新的lists,作为中介数据存放区

256.      list<T,alloc> carry;

257.      list<T,alloc> counter[64];

258.      intfill = 0;

259.      while (!empty())

260.      {

261.          carry.splice(carry.begin(), *this, begin());

262.          inti = ;

263.          while (i < fill && !counter[i].empty())

264.          {

265.              counter[i].merger(carry);

266.              carry.swap(counter[i++]);

267.          }

268.          carry.swap(counter[i]);

269.          if (i == fill)

270.              ++fill;

271.      }

272.      for (int i= 1; i < fill; ++i)

273.          counter[i].merge(counter[i - 1]);

274.      swap(counter[fill- 1]);

275.  }

276.   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值