Chapter 3 double-linked table

Source: Internet
Author: User

Chapter 3

Double-linked table
After a single-linked table is completed, it is the turn of double-linked tables.

3.1 code implementation
The implementation of double-stranded tables is as follows:

//////////////////////////////////////// ///////////////////////////////////////
//
// Filename: Dlist. h
// Version 0.10
// Author: Luo Cong
// Date: 2005-1-4 10:33:21
// Comment:
//
//////////////////////////////////////// ///////////////////////////////////////

# Ifndef _ double_list_h __
# DEFINE _ double_list_h __

# Include <assert. h>
# Include <crtdbg. h>

# Ifdef _ debug
# Define debug_new new (_ normal_block, this_file, _ line __)
# Endif

# Ifdef _ debug
# Define new debug_new
# UNDEF this_file
Static char this_file [] = _ file __;
# Endif

# Ifdef _ debug
# Ifndef assert
# Define assert
# Endif
# Else // not _ debug
# Ifndef assert
# Define assert
# Endif
# Endif // _ debug

Template <typename T>
Class cNode
{
Public:
T data;
CNode <t> * Prior;
CNode <t> * next;
CNode (): Data (T (), prior (null), next (null ){}
CNode (const T & initdata): Data (initdata), prior (null), next (null ){}
};

Template <typename T>
Class cdlist
{
Protected:
Int m_ncount;
CNode <t> * m_pnodehead;
CNode <t> * m_pnodetail;

Public:
Cdlist ();
Cdlist (const T & initdata );
~ Cdlist ();

Public:
Int isempty () const;
Int getcount () const;
Int insertbefore (const int POs, const t data );
Int insertafter (const int POs, const t data );
Int addhead (const t data );
Int addtail (const t data );
Void removeat (const int POS );
Void removehead ();
Void removetail ();
Void removeall ();
T & gettail ();
T gettail () const;
T & gethead ();
T gethead () const;
T & getat (const int POS );
T getat (const int POS) const;
Void setat (const int POs, t data );
Int find (const t data) const;
T & getprev (Int & Pos );
T & getnext (Int & Pos );
};

Template <typename T>
Inline cdlist <t >:: cdlist (): m_ncount (0), m_pnodehead (null), m_pnodetail (null)
{
}

Template <typename T>
Inline cdlist <t >:: cdlist (const T & initdata)
: M_ncount (0), m_pnodehead (null), m_pnodetail (null)
{
Addhead (initdata );
}

Template <typename T>
Inline cdlist <t> ::~ Cdlist ()
{
Removeall ();
}

Template <typename T>
Inline T & cdlist <t>: getnext (Int & Pos)
{
Assert (0! = M_ncount );
Assert (1 <= POS & Pos <= m_ncount );

Int I;
CNode <t> * ptmpnode = m_pnodehead;

For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}

++ Pos;

Return ptmpnode-> data;
}

Template <typename T>
Inline T & cdlist <t>: getprev (Int & Pos)
{
Assert (0! = M_ncount );
Assert (1 <= POS & Pos <= m_ncount );

Int I;
CNode <t> * ptmpnode = m_pnodehead;

For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}

-- Pos;

Return ptmpnode-> data;
}

Template <typename T>
Inline int cdlist <t >:: insertbefore (const int POs, const t data)
{
Int I;
Int nretpos;
CNode <t> * ptmpnode;
CNode <t> * pnewnode;

Pnewnode = new cNode <t>;
If (null = pnewnode)
{
Nretpos = 0;
Goto exit0;
}

Pnewnode-> DATA = data;

// If the list is empty, replace the head node with the new node.
If (null = m_pnodehead)
{
Pnewnode-> prior = NULL;
Pnewnode-> next = NULL;
M_pnodehead = pnewnode;
M_pnodetail = pnewnode;
Nretpos = 1;
Goto exit1;
}

// Is POS range valid?
Assert (1 <= POS & Pos <= m_ncount );

// Insert before head node?
If (1 = POS)
{
Pnewnode-> prior = NULL;
Pnewnode-> next = m_pnodehead;
M_pnodehead-> prior = pnewnode;
M_pnodehead = pnewnode;
Nretpos = 1;
Goto exit1;
}

// If the list is not empty and is not inserted before head node,
// Seek to the POS of the list and insert the new node before it.
Ptmpnode = m_pnodehead;
For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}
Pnewnode-> next = ptmpnode;
Pnewnode-> prior = ptmpnode-> prior;

Ptmpnode-> prior-> next = pnewnode;
Ptmpnode-> prior = pnewnode;

// If tail node, must update m_pnodetail
If (null = pnewnode-> next)
{
M_pnodetail = pnewnode;
}

Nretpos = Pos;

Exit1:
++ M_ncount;
Exit0:
Return nretpos;
}

Template <typename T>
Inline int cdlist <t >:: insertafter (const int POs, const t data)
{
Int I;
Int nretpos;
CNode <t> * pnewnode;
CNode <t> * ptmpnode;

Pnewnode = new cNode <t>;
If (null = pnewnode)
{
Nretpos = 0;
Goto exit0;
}

Pnewnode-> DATA = data;

// If the list is empty, replace the head node with the new node.
If (null = m_pnodehead)
{
Pnewnode-> prior = NULL;
Pnewnode-> next = NULL;
M_pnodehead = pnewnode;
M_pnodetail = pnewnode;
Nretpos = 1;
Goto exit1;
}

// Is POS range valid?
Assert (1 <= POS & Pos <= m_ncount );

// If the list is not empty,
// Seek to the POS of the list and insert the new node after it.
Ptmpnode = m_pnodehead;
For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}

Pnewnode-> next = ptmpnode-> next;
Pnewnode-> prior = ptmpnode;

// If newnode's position is m_pnodetail, update m_pnodetail
If (ptmpnode-> next = m_pnodetail)
{
M_pnodetail-> prior = pnewnode;
}

Ptmpnode-> next = pnewnode;

// If tail node, must update m_pnodetail
If (null = pnewnode-> next)
{
M_pnodetail = pnewnode;
}

Nretpos = POS + 1;

Exit1:
++ M_ncount;
Exit0:
Return nretpos;
}

Template <typename T>
Inline T & cdlist <t>: getat (const int POS)
{
Assert (1 <= POS & Pos <= m_ncount );

Int I;
CNode <t> * ptmpnode = m_pnodehead;

For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}

Return ptmpnode-> data;
}

Template <typename T>
Inline t cdlist <t >:: getat (const int POS) const
{
Assert (1 <= POS & Pos <= m_ncount );

Int I;
CNode <t> * ptmpnode = m_pnodehead;

For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}

Return ptmpnode-> data;
}

Template <typename T>
Inline int cdlist <t >:: addhead (const t data)
{
Return insertbefore (1, data );
}

Template <typename T>
Inline int cdlist <t >:: addtail (const t data)
{
Return insertafter (getcount (), data );
}

Template <typename T>
Inline cdlist <t >:: isempty () const
{
Return 0 = m_ncount;
}

Template <typename T>
Inline cdlist <t >:: getcount () const
{
Return m_ncount;
}

Template <typename T>
Inline T & cdlist <t>: gettail ()
{
Assert (0! = M_ncount );
Return m_pnodetail-> data;
}

Template <typename T>
Inline t cdlist <t>: gettail () const
{
Assert (0! = M_ncount );
Return m_pnodetail-> data;
}

Template <typename T>
Inline T & cdlist <t>: gethead ()
{
Assert (0! = M_ncount );
Return m_pnodehead-> data;
}

Template <typename T>
Inline t cdlist <t>: gethead () const
{
Assert (0! = M_ncount );
Return m_pnodehead-> data;
}

Template <typename T>
Inline void cdlist <t>: removeat (const int POS)
{
Assert (1 <= POS & Pos <= m_ncount );

Int I;
CNode <t> * ptmpnode = m_pnodehead;

// Head node?
If (1 = POS)
{
M_pnodehead = m_pnodehead-> next;
Goto exit1;
}

For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}
Ptmpnode-> prior-> next = ptmpnode-> next;

Exit1:
Delete ptmpnode;
-- M_ncount;
If (0 = m_ncount)
{
M_pnodetail = NULL;
}
}

Template <typename T>
Inline void cdlist <t>: removehead ()
{
Assert (0! = M_ncount );
Removeat (1 );
}

Template <typename T>
Inline void cdlist <t>: removetail ()
{
Assert (0! = M_ncount );
Removeat (m_ncount );
}

Template <typename T>
Inline void cdlist <t>: removeall ()
{
Int I;
Int ncount;
CNode <t> * ptmpnode;

Ncount = m_ncount;
For (I = 0; I <ncount; ++ I)
{
Ptmpnode = m_pnodehead-> next;
Delete m_pnodehead;
M_pnodehead = ptmpnode;
}

M_ncount = 0;
}

Template <typename T>
Inline void cdlist <t >:: setat (const int POs, t data)
{
Assert (1 <= POS & Pos <= m_ncount );

Int I;
CNode <t> * ptmpnode = m_pnodehead;

For (I = 1; I <Pos; ++ I)
{
Ptmpnode = ptmpnode-> next;
}
Ptmpnode-> DATA = data;
}

Template <typename T>
Inline int cdlist <t>: Find (const t data) const
{
Int I;
Int ncount;
CNode <t> * ptmpnode = m_pnodehead;

Ncount = m_ncount;
For (I = 0; I <ncount; ++ I)
{
If (Data = ptmpnode-> data)
Return I + 1;
Ptmpnode = ptmpnode-> next;
}

Return 0;
}

# Endif/_ double_list_h __

The call is as follows:

//////////////////////////////////////// ///////////////////////////////////////
//
// Filename: Dlist. cpp
// Version 0.10
// Author: Luo Cong
// Date: 2005-1-4 10:58:22
// Comment:
//
//////////////////////////////////////// ///////////////////////////////////////

# Include <iostream>
# Include "Dlist. H"
Using namespace STD;

Int main ()
{
Int I;
Int ncount;
Cdlist <int> Dlist;

# Ifdef _ debug
_ Crtsetdbgflag (_ crtdbg_alloc_mem_df | _ crtdbg_leak_check_df );
# Endif

Dlist. addtail (1 );
Dlist. addtail (3 );
Dlist. insertbefore (2, 2 );
Dlist. addhead (4 );
Dlist. removetail ();

Ncount = Dlist. getcount ();
For (I = 1; I <= ncount ;)
{
Cout <Dlist. getnext (I) <Endl;
}
}

3.2 description
A single-linked table has only one pointer pointing to a direct successor node. Therefore, starting from a node, you can only query other nodes following the pointer. If I want to access the previous node of a certain node, wouldn't I have to start from the header node again? Low Efficiency! In other words, in a single-chain table, the time complexity of getnext () is O (1), while that of getprev () is O (n ). To overcome the unidirectional disadvantage of a single-chain table, we can use -- "Dangdang", only you, is -- double-chain table.

As the name suggests, there are two pointers in the node of the double-stranded table, one pointing to the direct successor, and the other pointing to the direct precursor, which is shown in the C ++ language as follows:

Struct Node
{
Struct node * Prior;
Struct node * next;
T data;
};

Most operations on double-stranded tables (only operations involving pointers in the backward direction) are the same as those on single-stranded tables, but they are quite different in insertion and deletion, you must modify the pointer in both directions in the double-link table. Therefore, you can directly inherit the single-chain table class to complete the double-chain table, and then modify different functions. But I didn't do this. Don't ask why or what the character is.

If you are familiar with the pointer field of a single-chain table, this part of the double-chain table should be difficult for you. Read the code. If there is a bug, please let me know. Pai_^
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.