C++ 实现双链表

DoublyLinkedList.h

#pragma once

#include <iostream>
using namespace std;

/**
* 在C++实现的双链表中,双向链表的声明和实现都在头文件中。
* 这与"将声明和实现分离,头文件中尽量只包含声明"是相矛盾的! 那么为什么要这么做呢?
* 这是因为,在实现双向链表的实现,采用了模板;而C++编译器不能支持对模板的分离式编译!
* 简单点说,如果在DoublyLinkedList.h中声明,而在DoublyLinkedList.cpp中进行实现;
* 这样做的话,DoublyLinkedList.cpp中创建DoublyLink的对象时,会编译出错。
*/

template<class T>
struct Node
{
public:
    T value;
    Node *prev;
    Node *next;

    Node() {}
    Node(T t, Node *prev, Node *next)
    {
        this->value = t;
        this->prev = prev;
        this->next = next;
    }
};

template<class T>
class DoublyLink
{
public:
    DoublyLink();
    ~DoublyLink();

    int Size();
    int IsEmpty();

    T Get(int index);
    T GetFirst();
    T GetLast();

    int Insert(int index, T t);
    int InsertFirst(T t);
    int InsertLast(T t);

    int Del(int index);
    int DeleteFirst();
    int DeleteLast();

private:
    int count;
    Node<T> *phead;
    Node<T>* GetNode(int index);
};

// 构造函数
template<class T>
DoublyLink<T>::DoublyLink() : count(0)
{
    // 创建表头。这里表头不存储数据。
    phead = new Node<T>();
    phead->prev = phead->next = phead;

    //count = 0;
}

//析构函数
template<class T>
DoublyLink<T>::~DoublyLink()
{
    Node *ptmp;
    Node *pnode = phead->next;
    while (pnode != phead)
    {
        ptmp = pnode;
        pnode = pnode->next;
        delete ptmp;
    }

    delete phead;
    phead = NULL;
}

template<class T>
int DoublyLink<T>::Size()
{
    return count;
}

template<class T>
int DoublyLink<T>::IsEmpty()
{
    return count == 0;
}

template<class T>
Node<T>* DoublyLink<T>::GetNode(int index)
{
    if (index < 0 || index >= count)
    {
        cout << "GetNode failed! Index is out of range." << endl;
        return NULL;
    }

    /// count = 6
    ///   ↓—————————————————————————————————————————————————↑
    ///  □□□  <-> □□□ <-> □□□ <-> □□□ <-> □□□ <-> □□□ <-> □□□ 
    ///  ↓—————————————————————————————————————————————————↑
    ///  head      0       1       2       3       4       5

    // 正向查找
    if (index < count / 2)
    {
        int i = 0;
        Node<T> *pnode = phead->next;
        while ((i++) < index)
        {
            pnode = pnode->next;
        }
        return pnode;
    }

    int i = count - 1;
    Node<T> *pnode = phead->prev;
    while ((i--) > index)
    {
        pnode = pnode->prev;
    }
    return pnode;
}

template<class T>
T DoublyLink<T>::Get(int index)
{
    return GetNode(index)->value;
}

template<class T>
T DoublyLink<T>::GetFirst()
{
    return GetNode(0)->value;
}

template<class T>
T DoublyLink<T>::GetLast()
{
    return GetNode(count - 1)->value;
}

template<class T>
int DoublyLink<T>::Insert(int index, T t)
{
    if (index == 0)
        return InsertFirst(t);

    Node<T> *pindex = GetNode(index);

    Node<T> *pnode = new Node<T>(t, pindex->prev, pindex);
    pindex->prev->next = pnode;
    pindex->prev = pnode;

    count++;

    return 0;
}

template<class T>
int DoublyLink<T>::InsertFirst(T t)
{
    Node<T> *pnode = new Node<T>(t, phead, phead->next);
    phead->next->prev = pnode;
    phead->next = pnode;

    count++;

    return 0;
}

template<class T>
int DoublyLink<T>::InsertLast(T t)
{
    Node<T> *pnode = new Node<T>(t, phead->prev, phead);
    phead->prev->next = pnode;
    phead->prev = pnode;

    count++;

    return 0;
}

template<class T>
int DoublyLink<T>::Del(int index)
{
    Node<T> *pnode = GetNode(index);

    pnode->next->prev = pnode->prev;
    pnode->prev->next = pnode->next;

    delete pnode;
    count--;

    return 0;
}

template<class T>
int DoublyLink<T>::DeleteFirst()
{
    return Del(0);
}

template<class T> 
int DoublyLink<T>::DeleteLast()
{
    return Del(count - 1);
}

DoublyLinkedList.cpp

#include <iostream>
#include <DoublyLinkedList.h>
#include <sstream>
using namespace std;

void int_test()
{
    int iarr[4] = { 10, 20, 30, 40 };

    cout << "\n----int_test----" << endl;

    DoublyLink<int> *link = new DoublyLink<int>();

    link->InsertFirst(iarr[0]);
    link->InsertLast(iarr[1]);
    link->Insert(1, iarr[2]);
    link->Insert(2, iarr[3]);

    cout << "IsEmpty:" << link->IsEmpty() << endl;
    cout << "Size:" << link->Size() << endl;

    int size = link->Size();
    for (int i = 0; i < size; i++)
    {
        cout << "第" << i << "个元素为:" << link->Get(i) << endl;
    }
}

void string_test()
{
    string sarr[4] = { "one", "two", "three", "four" };

    cout << "\n----string_test----" << endl;

    DoublyLink<string> *link = new DoublyLink<string>();

    link->InsertFirst(sarr[0]);
    link->InsertLast(sarr[1]);
    link->Insert(1, sarr[2]);
    link->Insert(2, sarr[3]);

    cout << "IsEmpty:" << link->IsEmpty() << endl;
    cout << "Size:" << link->Size() << endl;

    int size = link->Size();
    for (int i = 0; i < size; i++)
    {
        cout << "第" << i << "个元素为:" << link->Get(i) << endl;
    }
}

struct stu
{
    int id;
    char name[20];
};

static stu arr_stu[] =
{
    { 10,"andy" },
    { 20,"baby" },
    { 30,"city" },
    { 40,"dog" },
};

#define ARR_STU_SIZE ((sizeof(arrstu))/(sizeof(arrstu[0])))

void object_test()
{
    cout << "\n----object_test----" << endl;
    DoublyLink<stu> *link = new DoublyLink<stu>();

    link->InsertFirst(arr_stu[0]);
    link->InsertLast(arr_stu[1]);
    link->Insert(1, arr_stu[2]);
    link->Insert(2, arr_stu[3]);

    cout << "IsEmpty:" << link->IsEmpty() << endl;
    cout << "Size:" << link->Size() << endl;

    int size = link->Size();
    for (int i = 0; i < size; i++)
    {
        cout << "第" << i << "个元素为:" << link->Get(i).id << " " << link->Get(i).name << endl;
    }
}

int main()
{
    int_test();
    string_test();
    object_test();
    cout << endl;
    system("pause");
    return 0;
}

测试结果

这里写图片描述

参考:http://wangkuiwu.github.io/2013/01/01/dlink/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值