1. IntroductionThe previous 3.1 single-linked list in the operation process has a disadvantage, is that the latter node can not directly find the front node, which makes a lot of operations have to search for nodes from beginning to end, the algorithm efficiency becomes very low, the way to solve this problem is to redefine the node of the list of nodes so that each node has two pointers, one point to the precursor to the linked list.
Node definition
template<class T>
class DLLNode {
public:
DLLNode() {
next = prev = 0;
}
DLLNode(const T& el, DLLNode<T> *n = 0, DLLNode<T> *p = 0) {
info = el; next = n; prev = p;
}
T info;
DLLNode<T> *next, *prev;
};
The limitations of the methods defined in section 3.1 are that linked lists can only store integers. If you want the list to store floating point numbers or arrays. You have to re-write a similar set of code. However, it is better to declare this class only once and not to determine in advance what type of data it is stored in, and in C + + it is easy to do so with a template. To illustrate the use of templates in linked list processing, the template is used to define the linked list from this section, but examples of list operations still use linked lists that store integers.
2. Operation of a doubly linked listthe Doublylinkedlist class defines the operation of a doubly linked list
template<class T>
class DoublyLinkedList {
public:
DoublyLinkedList() {
head = tail = 0;
}
void addToDLLTail(const T&);//
Insert a node to the end of a doubly linked list
T deleteFromDLLTail();//
Delete the node at the end and return its value
~DoublyLinkedList() {
clear();
}
bool isEmpty() const {
return head == 0;
}
void clear();
void setToNull() {
head = tail = 0;
}
void addToDLLHead(const T&);
T deleteFromDLLHead();
T& firstEl();
T* find(const T&) const;
protected:
DLLNode<T> *head, *tail;
friend ostream& operator<<(ostream& out, const DoublyLinkedList<T>& dll) {
for (DLLNode<T> *tmp = dll.head; tmp != 0; tmp = tmp->next)
out << tmp->info << ‘ ‘;
return out;
}
};
here are just two ways to do this: insert a node to the end of a doubly linked list and delete the node at the end, and the rest of the method readers can refer to the code themselves. (1)Insert a node to the end of a doubly linked list
The following steps are specifically divided into:
- Create a new node and initialize three data members (info initialized to el,next initialized to null)
- Set the value of prev to tail
- Point tail to the newly joined node
- The next point of the predecessor node points to the newly added node
template<class T>
void DoublyLinkedList<T>::addToDLLTail(const T& el) {
if (tail != 0) {
tail = new DLLNode<T>(el,0,tail);
tail->prev->next = tail;
}
else head = tail = new DLLNode<T>(el);
}
(2)Delete the node at the end
It is simpler to delete a node at the end of a doubly linked list because it does not require a loop to find the precursor node for the node to be deleted, tail points to the predecessor of the node to be deleted, and then sets the next node to be deleted to null. However, if the list to be operated on is an empty list, it may cause the program to crash, so the user should check whether the linked list is empty before deleting the end node, and check if the linked list is empty and the code is also provided.
if (!list.isEmpty())
n = list.deleteFromDLLTail();
else do not delete;
Another special case is that the list has only one node, and the head and tail are set to null.
Because the last node can be accessed directly, the time complexity of executing these two methods is O (1). Full code See: http://www.oschina.net/code/snippet_588162_48663
From for notes (Wiz)
List of attachments
3.2 Doubly linked list