直接上代码,亲测有用。

#ifndef __DLINK_H__
#define __DLINK_H__
/*
[phead] -> [index0] -> [index1] -> [index2] -> ...... [phead]
[phead] <- [index0] <- [index1] <- [index2] <- ...... [phead]
phead 不存储数据。 index是从0开始的。count = index + 1;
*/
template <class T>
struct node
{
public:
node(){}
node(T a, node *p1, node *p2)
{
this->data = a;
this->next = p2;
this->prev = p1;
}
node *next;
node *prev;
T data;
};
template <class T>
class Dlink
{
public:
Dlink();
~Dlink(); int create_Dlink();
int destroy_Dlink();
int getCount();
int insert_Dlink(int index, T tData);
int insert_Dlink_first(T tData);
int insert_Dlink_last(T tData);
T get_Dlink(int index);
T get_Dlink_first();
T get_Dlink_last();
int delete_Dlink(int index);
int delete_Dlink_first();
int delete_Dlink_last(); private:
node<T> *get_node(int index);
node<T> *m_pHead;
int m_nCount;
};
template <class T>
Dlink<T>::Dlink()
{
m_pHead = NULL;
m_nCount = ;
}
template <class T>
Dlink<T>::~Dlink()
{ }
template <class T>
node<T> *Dlink<T>::get_node(int index)
{
if(index < || index >= m_nCount)
{
cout << __FUNCTION__ << "() Error" << endl;
return NULL;
}
#if 0
node<T> *pnode = m_pHead->next;
int i = ;
while(i < m_nCount)
{
if(i == index)
{
return pnode;
}
pnode = pnode->next;
i++;
}
#else
// 正向查找
if(index <= m_nCount/)
{
int i = ;
node<T> *pnode = m_pHead->next;
while(i <= m_nCount/)
{
if(i == index)
{
return pnode;
}
pnode = pnode->next;
i++;
}
}
else // 反向查找
{
node<T> *pnode = m_pHead->prev;
int i = m_nCount - ; // 注意这里是必须要减一。因为m_nCount = index + 1;
while(i > (m_nCount/))
{
if(i == index)
{
return pnode;
}
pnode = pnode->prev;
i--;
}
}
#endif
return NULL;
}
template <class T>
int Dlink<T>::create_Dlink()
{
m_pHead = new node<T>();
m_pHead->next = m_pHead->prev = m_pHead; // 这个初始化非常重要
return ;
}
template <class T>
int Dlink<T>::destroy_Dlink()
{
if(!m_pHead)
{
cout << __FUNCTION__ << "() Error" << endl;
return -;
}
node<T> *pnode = m_pHead->next;
node<T> *tmp;
while(pnode != m_pHead)
{
tmp = pnode;
pnode = pnode->next;
delete tmp;
tmp = NULL;
}
delete m_pHead;
m_pHead = NULL;
m_nCount = ;
return ;
}
template <class T>
int Dlink<T>::getCount()
{
return m_nCount;
}
// index 表示要插入后的位置,所以这里可以等于m_nCount。表示在最后一个
template <class T>
int Dlink<T>::insert_Dlink(int index, T tData)
{
if(!m_pHead)
{
cout << __FUNCTION__ << "() Error" << endl;
return -;
}
if(index < || index > m_nCount)
{
cout << __FUNCTION__ << "() Error" << endl;
return -;
}
if(index == )
{
return insert_Dlink_first(tData);
}
if(index == m_nCount)
{
return insert_Dlink_last(tData);
}
node<T> *pindex = get_node(index);
node<T> *pnode = new node<T>(tData, pindex->prev, pindex);
pindex->prev->next = pnode; #if 0 // 20180223 update. 突然发现这里写错了
pindex->next->prev = pnode;
#endif
  pindex->prev = pnode; // 改为这样

m_nCount++;
return ;
}
template <class T>
int Dlink<T>::insert_Dlink_first(T tData)
{
if(!m_pHead)
{
cout << __FUNCTION__ << "() Error" << endl;
return -;
}
node<T> *pnode = new node<T>(tData, m_pHead, m_pHead->next);
if(!pnode)
{
cout << __FUNCTION__ << "() Error step1 " << endl;
return -;
}
m_pHead->next->prev = pnode;
m_pHead->next = pnode;
m_nCount++;
return ;
}
template <class T>
int Dlink<T>::insert_Dlink_last(T tData)
{
if(!m_pHead)
{
cout << __FUNCTION__ << "() Error" << endl;
return -;
}
node<T> *pnode = new node<T>(tData, m_pHead->prev, m_pHead);
if(!pnode)
{
cout << __FUNCTION__ << "() Error step1 " << endl;
return -;
}
m_pHead->prev->next = pnode;
m_pHead->prev = pnode;
m_nCount++;
return ;
}
template <class T>
T Dlink<T>::get_Dlink(int index)
{
node<T> *pnode = get_node(index);
if(!pnode)
{
cout << __FUNCTION__ << "() Error" << endl;
return NULL;
}
return pnode->data;
}
template <class T>
T Dlink<T>::get_Dlink_first()
{
return get_Dlink();
}
template <class T>
T Dlink<T>::get_Dlink_last()
{
return get_Dlink(count - );
}
// index 是从0开始编号的。这里的范围是 0 -- m_nCount-1
template <class T>
int Dlink<T>::delete_Dlink(int index)
{
if(index < || index >= m_nCount)
{
cout << __FUNCTION__ << "() Error" << endl;
return -;
}
node<T> *pnode = get_node(index);
if(pnode)
{
pnode->next->prev = pnode->prev;
pnode->prev->next = pnode->next;
delete pnode;
pnode = NULL;
m_nCount--;
}
return -;
}
template <class T>
int Dlink<T>::delete_Dlink_first()
{
return delete_Dlink();
}
template <class T>
int Dlink<T>::delete_Dlink_last()
{
return delete_Dlink(m_nCount - );
} #endif // __DLINK_H__

测试:

#include<iostream>
#include"dlink.h"
using namespace std;
void fun1()
{
cout << "fun1() +++" << endl;
/* // node test
node<int> *p1 = (node<int>*)malloc(sizeof(node<int>));
p1->data = 33;
cout << "data = " << p1->data << endl;
node<int> p;
p.data = 30;
*/
Dlink<int> *pDlink = new Dlink<int>;
pDlink->create_Dlink();
int arr[] = {, , , , };
for(int i = ; i < ; i++)
{
pDlink->insert_Dlink(, arr[i]);
// pDlink->insert_Dlink_last(arr[i]);
}
pDlink->insert_Dlink(, );
// pDlink->delete_Dlink(1);
// pDlink->destroy_Dlink();
int count = pDlink->getCount();
cout << "fun1() count:" << count << endl;
for(int i = ; i < count; i++)
{
int data = pDlink->get_Dlink(i);
cout << "index:" << i << " - data:" << data << endl;;
}
cout << "fun1() ---" << endl;
}
int main()
{
cout << "main() +++" << endl;
fun1();
cout << "main() ---" << endl;
return ;
}

关于为何C++的模板类声明和实现要放在一起可以参考:http://www.cnblogs.com/xcywt/p/8039574.html

一个简单的双向链表(C++实现)的更多相关文章

  1. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

  2. 在Openfire上弄一个简单的推送系统

    推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...

  3. ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面

    前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...

  4. 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库

    57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...

  5. 如何开发一个简单的HTML5 Canvas 小游戏

    原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...

  6. CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能

    CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...

  7. CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator

    CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator 我还没有用过Compute Shader,所以现在把红宝书里的例子拿来了,加入CSharpGL中. ...

  8. 应用OpenMP的一个简单的设计模式

    小喵的唠叨话:最近很久没写博客了,一是因为之前写的LSoftmax后馈一直没有成功,所以在等作者的源码.二是最近没什么想写的东西.前两天,在预处理图片的时候,发现处理200w张图片,跑了一晚上也才处理 ...

  9. 用php实现一个简单的链式操作

    最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...

随机推荐

  1. PHP面试随笔

    1.常见的HTTP状态码: 1xx系列:代表请求已被接受,需要继续处理 2xx系列:代表请求已成功被服务器接收.理解并接受 200:表示请求已成功,请求所希望的响应头或数据体将随此响应返回 201:表 ...

  2. JS中的循环---最全的循环总结

    在讲循环的之前,先知道一下循环结构的执行步骤 1.声明循环变量: 2.判断循环条件; 3.执行循环体操作: 4.更新循环变量: 5.然后循环执行2-4,直到条件不成立,跳出循环. 1while循环 v ...

  3. nodejs a和b文件相互引用

    //取自于node中文网 http://nodejs.cn/api/modules.html 当循环调用 require() 时,一个模块可能在未完成执行时被返回. 例如以下情况: a.js: con ...

  4. UWP 返回顶部按钮

    返回顶部的按钮,like this 当用户下滑了一定的距离之后,通常是快滑倒底部的时候,出现返回顶部按钮,当用户向上快滑,滑到顶部的时候,返回顶部按钮自动消失. 在UWP中,用来滚动内容的控件是Scr ...

  5. vue-router在ie9及以下history模式支持

    参考: https://www.npmjs.com/package/vue-route https://github.com/devote/HTML5-History-API 提要: ie9及以下不支 ...

  6. [最短路][模版]P1346 电车

    题目描述 在一个神奇的小镇上有着一个特别的电车网络,它由一些路口和轨道组成,每个路口都连接着若干个轨道,每个轨道都通向一个路口(不排除有的观光轨道转一圈后返回路口的可能).在每个路口,都有一个开关决定 ...

  7. AIO5程序中审批跳转条件:超过某一个值必须总经理审批

    以实际需求为例看下系统中如何设置: 客户需求:采购订单中对总金额进行限制,超过20000的话必须要经过总经理审批含税金额<20000:采购部门某个员工发起→直接主管批→财务主管知会含税金额≥20 ...

  8. android studio 默认 .gitignore 文件模板

    # built application files*.apk*.ap_ # files for the dex VM*.dex # Java class files*.class # generate ...

  9. Tomcat在修改代码后不会自动reload解决办法

    1.找到使用的Tomcat安装目录conf配置文件夹下context.xml文件 2.找到<Context>节点,改为<Context reloadable="true&q ...

  10. 题目1083:特殊乘法-九度oj

    题目描述: 写个算法,对2个小于1000000000的输入,求结果. 特殊乘法举例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5 输入: 两个小于1000000000的 ...