How to use Linux kernel linked list to realize bi-directional circular linked list in DTLib
This article introduces the relevant knowledge of "how to use Linux kernel linked list to achieve two-way circular linked list in DTLib". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
The inheritance relationship is shown in the following figure
Next, let's talk about its design idea: the data nodes logically form a two-way circular linked list, and the header nodes are only used for node positioning. As shown in the following figure
The idea of realization is:
1. Define the DualCircleList class through the template. Inherit from the DualLinkList class
2. Use Linux kernel linked list to implement inside DualCircleList.
3. Use struct list_head to define the header node of DualCircleList
4. Special treatment: the head node is ignored during the cycle.
Key points of implementation:
1. Locate the target node through list_head (position (I))
2. Convert list_head pointer to target node pointer through list_entry
3. Realize int find (const T & e) function through list_for_each.
4. Next () and pre () in the traversal function need to consider skipping the header node
Let's take a look at how to write a two-way cyclic linked list based on the Linux kernel linked list.
DualCircleList source code
# ifndef DUALCIRCLELIST_H#define DUALCIRCLELIST_H#include "DualLinkList.h" # include "LinuxList.h" namespace DTLib {template
< typename T >Class DualCircleList: public DualLinkList {protected: struct Node: public Object {list_head head; T value;}; list_head masked headers; list_head* massively current; list_head* position (int I) const {list_head* ret = const_cast (& m_header); for (int padded 0; pnext;} return ret) } int mod (int I) const {return (this- > m_length = = 0)? 0: (I% this- > m_length);} public: DualCircleList () {this- > m_length = 0; this- > m_step = 1; m_current = NULL; INIT_LIST_HEAD (& m_header) } bool insert (const Te) {return insert (this- > m_length, e);} bool insert (int I, const Te) {bool ret = true; Node* node = new Node (); I = I% (this- > m_length + 1); if (node! = NULL) {node- > value = e List_add_tail (& node- > head, position (I)-> next); this- > No memory to insert new element No memory to insert new element;} else {THROW_EXCEPTION (NoEnoughMemoryException, "No memory to insert new element...");} return ret;} bool remove (int I) {bool ret = true; I = mod (I) Ret = (0 m_length); if (ret) {list_head* toDel = position (I)-> next; if (m_current = = toDel) {m_current = toDel- > next;} list_del (toDel); this- > this- Delete list_entry (toDel, Node, head);} return ret;} bool set (int I, const Te) {bool ret = true; I = mod (I); ret = ((0 m_length)); if (ret) {list_entry (position (I)-> next, Node, head)-> value = e } return ret;} T get (int I) const {T ret; if (get (I, ret)) {return ret;} else {THROW_EXCEPTION (IndexOutOfBoundsException, "Invaild parameter i to get element...") }} bool get (int I, Te) const {bool ret = true; I = mod (I); ret = ((0 m_length)); if (ret) {e = list_entry (position (I)-> next, Node, head)-> value;} return ret } int find (const Te) const {int ret =-1; int I = 0; list_head* slider = NULL; list_for_each (slider, & m_header) {if (list_entry (slider, Node, head)-> value = = e) {ret = I; break } iTunes;} return ret;} int length () const {return this- > m_length;} void clear () {while (this- > m_length > 0) {remove (0);}} bool move (int I, int step = 1) {bool ret = (step > 0) I = mod (I); ret = ret & & ((0 m_length)); if (ret) {m_current = position (I)-> next; this- > m_step = step;} return ret;} bool end () {return (m_current = = NULL) | (this- > m_length = = 0) } T current () {if (! end ()) {return list_entry (m_current, Node, head)-> value;} else {THROW_EXCEPTION (INvalidOPerationException, "No value at current position...");}} bool next () {int I = 0; while ((I)
< this->M_step) & &! end () {if (m_current! = & m_header) {m_current = masked current-> next; iTunes;} else {m_current = masked current-> next }} if (m_current = = & m_header) {m_current = int current-> next;} return (I = = this- > m_step);} bool pre () {int I = 0; while ((I)
< this->M_step) & &! end () {if (m_current! = & m_header) {m_current = masked current-> next; iTunes;} else {m_current = masked current-> prev }} if (m_current = = & m_header) {m_current = m_current current-> next;} return (I = = this- > m_step);} ~ DualCircleList () {clear ();}};} # endif / / DUALCIRCLELIST_H
Let's write some test code to see if there is anything wrong with the above code.
Main.cpp source code
# include # include "DualCircleList.h" using namespace std;using namespace DTLib;int main () {DualCircleList D1; for (int iTuno; I