【C++】模版实现双向链表的各种操作(如:逆置、去重Unique、分类(冒泡)、合并)

原创 2016年05月30日 17:18:03

在cplusplus.com里,我们可以搜索list来查看库是如何实现双向链表的。当然,我们也可以在平时使用时包上头文件list来调用C++里的list库。在这里,我今天就不再赘述用C语言或者C++未引入模版这两种场景来向大家分享双向链表了,而是注重多类型都可以使用双向链表。也就是我们今天的主题:模版实现双向链表。


我主要实现了尾插、尾删、打印、去重、逆置等等一系列操作,而关于像Insert()、Erase()之类的操作我并没有在这里全部实现,一方面是因为之前我们反复实现过,如果你感兴趣的话,可以查看我之前的博客。另一方面,我出于较为低效不常见的原因。希望大家理解。


另外,需要说明的一点是,今天我使用的均是类内声明,类外定义的方式。

代码如下:


#include<iostream>
using namespace std;

template<class T>
struct ListNode
{
    ListNode(const T& x)
    :_next(NULL)
    , _prev(NULL)
    , _data(x)
    {}

    ListNode<T>* _next;
    ListNode<T>* _prev;
    T _data;
}; 

template<class T>
class List
{
public:
    List()
        :_head(NULL)
        , _tail(NULL)
    {}

    List(const List<T>& l)
    {
        ListNode<T>* cur = l._head;
        while (cur)
        {
            this->PushBack(cur->_data);
            cur = cur->_next;
        }
    }

    List<T>& operator=(const List<T>& l)
    {
        //先删除节点,再插入节点
        if (&s != this)
        {
            ListNode<T>* pcur = _head;
            while (pcur)
            {
                ListNode<T>* del = pcur;
                pcur = pcur->_next;
                delete del;
                del = NULL;                
            }

            ListNode<T>* cur = _head;
            while (cur)
            {
                this->PushBack(cur->_data);
                cur = cur->_next;
            }
        }
        return *this;
    }

    ~List()//一个节点一个节点的删除
    {
        ListNode<T>* cur = _head;
        while (cur)
        {
            ListNode<T>* del = cur;
            cur = cur->_next;
            delete del;
            del = NULL;
        }
    }
    
    void PushBack(const T& x);
    void PopBack();
    void Unique();
    void PrintList();
    void Reverse();
    int Length();
    void Sort();
     void Merge(List<T>& l2);

protected:
    ListNode<T>* _head;
    ListNode<T>* _tail;
};


//尾插
template<class T>
void List<T>::PushBack(const T& x)
{
    //分析:分为两种情况:无节点、有节点
    if (_head == NULL)
    {
        _head = _tail = new ListNode<T>(x);
    }
    else
    {
        ListNode<T>* cur = new ListNode<T>(x);
        _tail->_next = cur;
        cur->_prev = _tail;
        _tail = cur;
        _tail->_next = NULL;
    }
}

//尾删
template<class T>
void List<T>::PopBack()
{
    //分析:分为三种情况:无节点、一个节点、多个节点
    if (_head == _tail)
    {
        if (_head == NULL)
        {
            return;
        }
        else
        {
            delete _head;
            _head = _tail = NULL;
        }
    }
    else
    {
        ListNode<T>* prev = _tail->_prev;
        delete _tail;
        _tail = NULL;
        _tail = prev;
        _tail->_next = NULL;
    }
}

//去重:前提是针对已排序的有重复数据的链表
//template<class T>
//void List<T>::Unique()
//{
//    //分析:分为三种情况:无节点一个节点(无需删除节点)、两个节点、两个以上节点
//    if (_head == _tail)
//    {
//        return;    
//    }
//    else
//    {
//        ListNode<T>* pcur = _head;
//        ListNode<T>* pnext = _head->_next;
//        if (pnext->_next == NULL)    //两个节点
//        {
//            if (pcur->_data == pnext->_data)
//            {
//                delete pnext;
//                pnext = NULL;
//                _tail = _head = pcur;
//                return;
//            }
//            else
//            {
//                return;
//            }            
//        }
//        else
//        {
//            //两个以上节点
//            ListNode<T>* cur = _head;
//            while (cur->_next)
//            {
//                ListNode<T>* next = cur->_next;
//                ListNode<T>* nextnext = next->_next;
//                if (cur->_data == next->_data)
//                {
//                    cur->_next = nextnext;
//                     nextnext->_prev = cur;
//                    delete next;
//                    next = NULL;
//                }
//                cur = cur->_next;
//            }
//        }                                     
//    }    
//}

//逆置
template<class T>
void List<T>::Reverse()
{
    //分析:从两头开始走,交换数据(分奇数个数据和偶数个数据)
    ListNode<T>* begin = _head;
    ListNode<T>* end = _tail;
    while (!((begin == end) || end->_next == begin))
    {
        swap(begin->_data, end->_data);
        begin = begin->_next;
        end = end->_prev;
    }
}

//长度
template<class T>
int List<T>::Length()
{
    ListNode<T>* cur = _head;
    int count = 0;
    while (cur)
    {
        count++;
        cur = cur->_next;
    }
    return count;
}

//分类
template<class T>
void List<T>::Sort()
{
    //使用冒泡排序,实现升序或者降序
    ListNode<T>* i = _head;
    while (i != _tail)
    {
        ListNode<T>* j = _head;
        ListNode<T>* end = _tail;
        while (j != end)
        {
            if (j->_data >(j->_next)->_data)
            {
                swap(j->_data, (j->_next)->_data);
            }
            j = j->_next;
            
        }
        end = end->_prev;
        i = i->_next;
    }
}

//合并
template<class T>
void List<T>::Merge(List<T>& l2)
{
    ListNode<T>* cur1 = _head;
    ListNode<T>* cur2 = l2._head;
    if (cur1->_data > cur2->_data)
    {
        swap(cur1->_data, cur2->_data);
    }
    while (cur1 && cur2)
    {
        if (cur1->_data <= cur2->_data)
        {
            cur1 = cur1->_next;
        }
        else
        {
            ListNode<T>* tmp = cur2;
            cur2 = cur2->_next;
            ListNode<T>* prev = cur1->_prev;
            
            cur1->_prev = tmp;
            tmp->_next = cur1;

            prev->_next = tmp;
            tmp->_prev = prev;
        }
    }
    if (cur1 == NULL)
    {
        _tail->_next = cur2;
        cur2->_prev = _tail;
        _tail = l2._tail;
    }
}

//打印
template<class T>
void List<T>::PrintList()
{
    ListNode<T>* cur = _head;
    while (cur)
    {
        cout << cur->_data << "->";
        cur = cur->_next;
    }
    cout << "NULL" << endl;
}


void Test()
{
    List<int> l1;
    l1.PushBack(1);
    l1.PushBack(3);
    l1.PushBack(5);
    l1.PushBack(7);
    l1.PrintList();

    l1.PopBack();
    l1.PrintList();

    /*l1.Unique();
    l1.PrintList();*/

    List<int> l2;
    l2.PushBack(2);
    l2.PushBack(4);
    l2.PushBack(6);
    l1.Merge(l2);
    l1.PrintList();

    l1.Reverse();
    l1.PrintList();

    l1.Sort();
    l1.PrintList();

}

int main()
{
    Test();
    system("pause");
    return 0;
}


本文出自 “Han Jing's Blog” 博客,请务必保留此出处http://10740184.blog.51cto.com/10730184/1750695

单链表的创建(有头结点和无头结点)

1、有头结点的单链表的创建#include using namespace std;struct ListNode{ int val; ListNode *next; };//有头...

关于C++ const 的全面总结

C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助。Const 是C++中常用的类型修饰符,常类型是指使用类型...
  • Eric_Jo
  • Eric_Jo
  • 2009年04月30日 08:54
  • 286161

【C++】实现双向链表的所有操作,包括逆置双链表(三种方法)

建立源文件List.cppinclude "List.h" int main() {     Test();     system("pause");     return 0; }建立头文件Lis...

c++中的双向链表写法,主要实现(增删查改,链表逆置,构造函数,运算符重载,等)

c++中的双向链表写法,主要实现(增删查改,链表逆置,构造函数,运算符重载,等)本文主要内容1)介绍c++中双向链表的写法。2)实现双向链表中数据的增、删、查、改、链表逆置、链表输出3)介绍类中构造函...

数据结构——双向链表实现,基本操作的C++版

对于循环双向链表 判断一个链表是否为空的条件为:head->next==head (头指针) 判断*p为最后一个节点的条件为:p->next=head [cpp] v...

双向链表基础操作C++实现

Node.h:template struct Node { T val; Node* next; Node* prev; Node(T nVal) { ...

C++中的双向链表的实现

  • 2010年08月28日 12:09
  • 3KB
  • 下载

(C++版)链表(三)——实现双向链表的创建、插入、删除等简单操作

链表(三)

c++双向链表的实现

  • 2010年12月19日 18:16
  • 2KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【C++】模版实现双向链表的各种操作(如:逆置、去重Unique、分类(冒泡)、合并)
举报原因:
原因补充:

(最多只允许输入30个字)