当前位置:编程学习 > C/C++ >>

双向链表的实现

单链表是最基本最简单的结构了,用处也蛮多的吧,尤其是后面在层序结构的各种树与图结构的时候大量使用链表而且还很多是单链表形式的。学习双向链表还是由约瑟夫问题引入的呢,在单链表的删除操作时需要用并排的两个指针同步向后移动,为避免这个问题双向链表就派上用场了。双向链表顾名思义是每个结点有两个方向了,那么在结点里面不仅仅要保存一个后向指针还要保存一个前向指针了。
 
[cpp]  
#pragma once  
#include<iostream>  
using namespace std;  
template<class T>  
class LinkNode //节点类  
{  
public:           //全为公共的方便操作  
    T data; //模板类型的一个数据  
    LinkNode<T> *next; //该结点的一个指针,用于指向后继  
    LinkNode<T> *prior;//用于指向前驱  
public:  
    LinkNode(LinkNode<T> *ptr = NULL)//只初始化指针的构造函数,并使指针域为空  
    { next = ptr; prior = ptr; }  
  
    LinkNode(const T& item,LinkNode<T> *ptr = NULL)//数据与指针一同初始化的构造函数,依旧指针域默认参数为空  
    { data = item; next = ptr; prior = ptr; }  
  
    ~LinkNode(){}  
};  
双向链表在插入的时候搭链是一个很有讲究的过程,某些步骤是有严格顺序的:
 
 
[cpp]  
newNode->prior = current; //双向链表插入的关键四步,最后一句必须最后执行  
newNode->next = current->next;  
current->next->prior = newNode;  
current->next = newNode;  
大致上就是先搞定新结点的prior和next指针,然后是待插位置的后一个结点的prior和前一个结点的next了。
双向链表的删除直接是先保存待删除结点指针然后覆盖就行了,其他的操作基本可以看作是单链表了。
 
 
[cpp] 
#pragma once  
//#include"LinearList.h"  
#include"LinkNode.h"  
#include<iostream>  
using namespace std;  
template<class T>//继承的过程中,加上此句派生类依然为类模板  
class List  
{  
protected:  
    LinkNode<T>* first;//封装  
public:  
    List();  
    //List(const T& x);//感觉没用到过  
    List(List<T>& L);  
    ~List();  
    void makeEmpty();//依次销毁每个结点的空间  
       
    int Length() const;//搜索当前表节点数  
    LinkNode<T>* getHead() const;//返回头指针  
    LinkNode<T>* Search(T x) const;//搜索并返回指针  
    LinkNode<T>* Locate(int i) const;//定位并返回指针  
  
    bool GetData(int i,T& x) const;//返回第i个结点的元素值以引用的形式  
    bool SetData(int i,T& x);//修改第i个结点的元素值  
    bool Insert(int i,T& x);//在第i个节点后面插入新节点元素值  
    LinkNode<T>* Remove(int i,T& x);//删除第i个结点  
  
    bool isEmpty() const;//判表空  
  
    void Sort(); //排序  
    void input(T endTag);//建立表并输入  
    void output();//输出表  
    void operator = (List<T>& L);//复制重载  
};  
  
template<class T>  
List<T>::List()  
{  
    first = new LinkNode<T>;//构造函数中开辟头结点  
}  
  
template<class T>  
List<T>::List(List<T>& L)  
{  
    LinkNode<T> *srcptr = L.getHead() ->next; //获取头指针 用于遍历  
    LinkNode<T> *destptr = first = new LinkNode<T>;//建立头结点 初始化  
    LinkNode<T> *newNode;  
    T value;  
    while(srcptr != NULL)//直到最后一个结点的尾指针为空结束  
    {  
        value = srcptr->data;  
        newNode = new LinkNode<T>(value);  
  
        newNode->prior = destptr;//往新链表的后面插入  
        destptr->next = newNode;  
  
        srcptr = srcptr->next;//后移  
        destptr = destptr->next;  
    }  
}  
template<class T>  
List<T>::~List()  
{}  
  
template<class T>  
void List<T>::makeEmpty() //全部销毁指针资源  
{  
    LinkNode<T> *current = first->next;  
    LinkNode<T> *del;  
    while(current != NULL)  
    {  
        del = current;  
        current = current->next;  
        delete del;  
    }  
}  
  
template<class T>  
int List<T>::Length() const  
{  
    int count = 0;  
    LinkNode<T> *current = first;//头指针副本用于遍历  
    while(current->next != NULL)//与单链表的遍历控制条件相同,当前结点后后继是否为空  
    {  
        current = current->next;  
        count++ ;  
    }  
    return count;  
}  
  
template<class T>  
LinkNode<T>* List<T>::getHead() const  
{  
    return first;  
}  
template<class T>  
LinkNode<T>* List<T>::Search(T x) const  
{  
    LinkNode<T> *current = first->next;  
    while(current != NULL)//此时的控制条件为某个结点的next知否为空  
    {  
        if(current->data == x)  
            return current;//如果查询到直接函数返回,不用无用操作(如果链表中有多个x元素值,则以第一个为准返回)  
        current = current->next;  
    }  
    return NULL;  
}  
template<class T>  
LinkNode<T>* List<T>::Locate(int i) const  
{  
    if(i < 0)     //定位可以是第0个,也就是头结点指针  
  &nbs
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,