linked_list.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_CONTAINERS_LINKED_LIST_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_CONTAINERS_LINKED_LIST_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple LinkedList type. (See the Q&A section to understand how this 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differs from std::list). 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To use, start by declaring the class which will be contained in the linked 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list, as extending LinkNode (this gives it next/previous pointers). 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// class MyNodeType : public LinkNode<MyNodeType> { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ... 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// }; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Next, to keep track of the list's head/tail, use a LinkedList instance: 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LinkedList<MyNodeType> list; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To add elements to the list, use any of LinkedList::Append, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LinkNode::InsertBefore, or LinkNode::InsertAfter: 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LinkNode<MyNodeType>* n1 = ...; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LinkNode<MyNodeType>* n2 = ...; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LinkNode<MyNodeType>* n3 = ...; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list.Append(n1); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list.Append(n3); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// n3->InsertBefore(n3); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Lastly, to iterate through the linked list forwards: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for (LinkNode<MyNodeType>* node = list.head(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// node != list.end(); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// node = node->next()) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MyNodeType* value = node->value(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ... 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Or to iterate the linked list backwards: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for (LinkNode<MyNodeType>* node = list.tail(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// node != list.end(); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// node = node->previous()) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MyNodeType* value = node->value(); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ... 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Questions and Answers: 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Q. Should I use std::list or base::LinkedList? 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A. The main reason to use base::LinkedList over std::list is 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// performance. If you don't care about the performance differences 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// then use an STL container, as it makes for better code readability. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Comparing the performance of base::LinkedList<T> to std::list<T*>: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Erasing an element of type T* from base::LinkedList<T> is 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an O(1) operation. Whereas for std::list<T*> it is O(n). 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// That is because with std::list<T*> you must obtain an 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// iterator to the T* element before you can call erase(iterator). 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Insertion operations with base::LinkedList<T> never require 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap allocations. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Q. How does base::LinkedList implementation differ from std::list? 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A. Doubly-linked lists are made up of nodes that contain "next" and 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "previous" pointers that reference other nodes in the list. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// With base::LinkedList<T>, the type being inserted already reserves 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// space for the "next" and "previous" pointers (base::LinkNode<T>*). 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Whereas with std::list<T> the type can be anything, so the implementation 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needs to glue on the "next" and "previous" pointers using 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// some internal node type. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LinkNode { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode() : previous_(0), next_(0) {} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode(LinkNode<T>* previous, LinkNode<T>* next) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : previous_(previous), next_(next) {} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert |this| into the linked list, before |e|. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void InsertBefore(LinkNode<T>* e) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->next_ = e; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->previous_ = e->previous_; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e->previous_->next_ = this; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e->previous_ = this; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert |this| into the linked list, after |e|. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void InsertAfter(LinkNode<T>* e) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->next_ = e->next_; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->previous_ = e; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e->next_->previous_ = this; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e->next_ = this; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove |this| from the linked list. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveFromList() { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->previous_->next_ = this->next_; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->next_->previous_ = this->previous_; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode<T>* previous() const { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return previous_; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode<T>* next() const { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cast from the node-type to the value type. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T* value() const { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<const T*>(this); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* value() { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<T*>(this); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode<T>* previous_; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode<T>* next_; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LinkedList { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The "root" node is self-referential, and forms the basis of a circular 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list (root_.next() will point back to the start of the list, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and root_->previous() wraps around to the end of the list). 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkedList() : root_(&root_, &root_) {} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Appends |e| to the end of the linked list. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Append(LinkNode<T>* e) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e->InsertBefore(&root_); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode<T>* head() const { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return root_.next(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode<T>* tail() const { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return root_.previous(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LinkNode<T>* end() const { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &root_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkNode<T> root_; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_CONTAINERS_LINKED_LIST_H_ 165