/*
*简单的list双向链表结构关系
*
*李坤昱
*326087275@qq.com
*
*
*从简单到复杂的学习之路
*/#include <stdio.h>
template<typename T>
class listnode//观摩linux源码 listnode作为基类,T类 data放置在其派生类中,本例子没做其派生类
{
public:
listnode<T>* prior;//指向之前的地址
listnode<T>* next;//指向下一个地址
T data;//没做数据派生类 ,直接用节点类储存类型数据
int nrecord;//是否已经记录数据
int nend;//末端判断,用变量标志判断,主要是应对CString容器,而不判断T data
listnode()
{
nrecord = 0;
nend = 0;
}
virtual ~listnode(){}
};template<typename T>
class alloc//简单的内存分配
{
public:
virtual ~alloc(){}
listnode<T>* mallocmemory(listnode<T>* obj,int & capacity,bool  bClean = false);//第一个参数是传入的链表对象,第二个参数代表向前还是向后增加节点,第三个参数是否已经设置末端
};
template<typename T>
inline listnode<T>* alloc<T>::mallocmemory(listnode<T>* obj,int & capacity,bool  bClean)
{listnode<T> *_new_ = new listnode<T>;_new_->next = NULL;_new_->prior = NULL;
if (0 == capacity)//按照顺序向后增加节点
{
if (!bClean)
{
while(1 != obj->nend)
{
obj = obj->next;
}
obj->nend = 0;
}
obj->next = _new_;//alignment container
obj->next->prior = obj;
_new_->nend = 1;//末端结束标志
}
else//在第一位增加节点
{
obj->prior = _new_;
_new_->next = obj;
}
return _new_;
}template<typename T>
class List_Iterator//简单的迭代器
{
public:
typedef List_Iterator<T> list_Iter;
typedef listnode<T>* node;
typedef long int difference_type;
typedef T* pointer;
typedef T& reference;explicit List_Iterator():noperjia(1)
{}
pointer operator->()const
{
return &(m_Iternode->data);
}
reference operator*()const
{
return m_Iternode->data;
}
bool operator !=(list_Iter & obj)
{
return (noperjia != obj.noperjia);
}
int operator ++()
{
++noperjia;
m_Iternode = m_Iternode->next;
return 0;
}
int operator --()
{
--noperjia;
m_Iternode = m_Iternode->prior;
return 0;
}
node m_Iternode;
int noperjia;
};template<typename T>
class test
{
public:
virtual ~test()
{
Clean();
}
typedef listnode<T>* node;
typedef alloc<T> malloc;
typedef List_Iterator<T> iterator;
explicit test():nbefore(0),noperjia(1),bClean(true){
initnode();}
int initnode();
listnode<T>* allocmemory(int insert = 0,bool  bClean = false);//insert 0为向后 ,1为向前, bClean true第一次使用不计算位置 。链表多分配一节做末端
bool push_back(const T & obj);//从当前向后插入
bool push_front(const T & obj);//在第一位向前插入
bool eArse(iterator & obj);//容器删除,迭代器也跟着删除
iterator Begin();
iterator End();
bool Insert(iterator & obj,const T & _obj);//迭代也随着增加而增加
bool Clean();
protected:
node lastnode;
node beforenode;
node nextnode;
node endnode;
malloc alloc_type;
int nbefore;
int noperjia;
iterator iter;
private:
bool bClean;//判断是否清除过数据
};
template<typename T>
inline int test<T>::initnode()
{
listnode<T>* init = new listnode<T>;
init->prior = NULL;
init->next = NULL;
lastnode = init;
beforenode = init;
endnode = init;
return 0;
}template<typename T>
inline listnode<T>* test<T>::allocmemory(int insert,bool  bClean)
{
if (!insert)
{
endnode = alloc_type.mallocmemory(beforenode,insert,bClean);
endnode->next = lastnode;
lastnode->prior = endnode;
this->bClean = false;
return endnode;
}lastnode = alloc_type.mallocmemory(lastnode,insert);
lastnode->prior = endnode;
endnode->next = lastnode;
return lastnode;
}
template<typename T>
inline bool test<T>::push_back(const T & obj)
{
if (bClean)
{
initnode();
allocmemory(0,bClean);
bClean = false;
}
elseallocmemory(0);if(1 >= ++nbefore){beforenode->data = obj;beforenode->nrecord = 1;lastnode = beforenode;nextnode = beforenode->next;return true;}while(0  != beforenode->nrecord){beforenode = beforenode->next;}beforenode->data = obj;beforenode->nrecord = 1;nextnode = beforenode->next;return true;
}
template<typename T>
inline bool test<T>::push_front(const T & obj)
{
if (bClean)
{
initnode();
}
allocmemory(1);
if(1 >= ++nbefore)
{
lastnode->data = obj;
lastnode->nrecord = 1;
beforenode = lastnode;
nextnode = lastnode->next;
return true;
}
while(1  != lastnode->prior->nend)
{
lastnode = lastnode->prior;
}
lastnode->data = obj;
lastnode->nrecord = 1;
return true;
}
template<typename T>
inline List_Iterator<T> test<T>::Begin()
{
iter.m_Iternode = lastnode;
return iter;
}
template<typename T>
inline List_Iterator<T> test<T>::End()
{
iter.noperjia = (nbefore + 1);//用来判断是不是最后一节
iter.m_Iternode = beforenode;
return iter;
}
template<typename T>
inline bool  test<T>::Insert(iterator & obj,const T & _obj)//添加或者删除一节,都要为之前和之后的链表建立上下链接
{
if (bClean)
{
initnode();
bClean = false;
}
if (1 == obj.noperjia)//首节点  嵌入的数据为自己new空间,不用判断空间
{
node savenode = new listnode<T>;
savenode->data = _obj;
savenode->next = lastnode;
savenode->prior = endnode;
savenode->nrecord = 1;
endnode->next = savenode;
lastnode = savenode;
obj.m_Iternode = lastnode;
return true;
}
node Addnode;
Addnode = new listnode<T>;
Addnode->data = _obj;
obj.m_Iternode->prior->next = Addnode;
Addnode->prior = obj.m_Iternode->prior;
obj.m_Iternode->prior = Addnode;
Addnode->next = obj.m_Iternode;
Addnode->next->next = obj.m_Iternode->next;
obj.m_Iternode = obj.m_Iternode->prior;
lastnode = obj.m_Iternode;
while (!lastnode->prior->nend)//返回到第一位
lastnode = lastnode->prior;
return true;
}
template<typename T>
inline bool test<T>::eArse(iterator & obj)
{
if (bClean)
{
return false;
}
node getnode,savenode,deletenode;
if (1 == obj.noperjia)
{
if (!obj.m_Iternode->nrecord)
return false;
getnode = obj.m_Iternode->next;
deletenode = obj.m_Iternode;
delete deletenode;
obj.m_Iternode = getnode;
obj.m_Iternode->prior = endnode;
obj.m_Iternode->prior->next =  obj.m_Iternode;
lastnode = obj.m_Iternode;
if (obj.m_Iternode->nend || obj.m_Iternode->next->nend)
{
endnode->next  = obj.m_Iternode;
obj.m_Iternode->next = endnode;
return true;
}
return true;
}
getnode = obj.m_Iternode->prior;
deletenode = obj.m_Iternode;
savenode = obj.m_Iternode->next;
delete deletenode;
obj.m_Iternode = savenode;
obj.m_Iternode->prior = getnode;
obj.m_Iternode->prior->next = obj.m_Iternode;
lastnode = obj.m_Iternode;
while(!lastnode->prior->nend)
lastnode = lastnode->prior;
return true;
}
template<typename T>
bool test<T>::Clean()//把链表都删除释放掉,所有节点置为空
{
node deletenode;
while(!lastnode->prior->nend)//向前检查删除
{
deletenode = lastnode->prior;
delete lastnode;
lastnode = deletenode;
}
while(!lastnode->nend)//1为末端标志 向后删除
{
deletenode = lastnode->next;
delete lastnode;
lastnode = deletenode;
}
delete lastnode;
lastnode = NULL;
beforenode = NULL;
nextnode = NULL;
endnode = NULL;
iter.m_Iternode = NULL;
nbefore = 0;
noperjia = 0;
bClean = true;
return true;
}template<typename T>
class testlist : public test<T>//只是变个名称,没有实质用处
{
public:
~testlist(){}
testlist(){}
};/*使用实例
testlist<int>test;//或者test<int>test;
for(int i = 0;i < 100;i++)
{
test.push_back(1);
test.push_front(1);
}
for(testlist<int>::iterator it  = test.Begin();it != End();it++)
{
*it;//调用引用运算符,显示传入的类数据 比如it的值为1 。如果传入的是够类型是个结构体 可以输出成员数据 ,也可以使用指针运算符 it->data;
test.Insert(it,1);//根据当前迭代到的链接位置插入数据,比如现在是第7位链表,插入第7位链表,原来的第7位变成第8位
test.eArse(it,1);//删除当前的链接节点,比如删除第7位,原来的第8位变为第7位。  Insert与eArse 整个迭代循环中就可以一直使用,
避免了STL中使用earse不调用break出现崩溃的问题。}//迭代器独立出来的好处:可以避免因为迭代器的释放而导致链表地址的丢失问题。test.Clear();//使用完成testlist调用,释放链接内存。  也可以不用调用此方法,testlist对象销毁时会自动调用析构函数,析构函数内部放入了此方法。
*/1.迭代器 按照我个人的实现思路,迭代器作用是用来查询链表数据位置,并且更新链表数据。在例子中,通过迭代器添加或者删除链表节点,并且刷新list的链表对象,有效的防止迭代过程中删除节点导致的崩溃问题。
2.内存分配双向链表的构建在内存分配时就已经做好了工作,并且多出一节末端用来判断数据,有效的预防了比如CString容器类不好判断的问题。
3.链表方法类通过此类建立内存分配、迭代器、与链表类的关联,简单而且灵活。源文件地址http://download.csdn.net/detail/a29562268/9714680首次写博客,有许多理解不到的地方,请帮忙指出,谢谢~!

STL之双向循环链表(List)的内部关系相关推荐

  1. 【数据结构】带头双向循环链表的增删查改(C语言实现)

    文章目录 前言 一.什么是带头双向循环链表 二.带头双向循环链表的实现 1.结构的定义 2.链表的初始化 3.开辟新节点 4.在头部插入数据 5.在尾部插入数据 6.查找数据 7.在pos位置之前插入 ...

  2. 数据结构-单向循环链表、双向循环链表、仿真链表

    一.单向循环链表: 1.概念: 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环. 和单链表相比,循环单链表的 ...

  3. 数据结构与算法 | 带头双向循环链表

    上一节里实现的是最简单的链表,在实际中那种链表不会单独用来存储数据,更多是作为其他数据结构的子结构,如图的邻接表等.而比较常用的就是带头双向循环链表. 通过对比我们可以看出有三个不同,多了头节点,链表 ...

  4. 数据结构-线性表之带头结点的双向循环链表

    文章目录 前言 实现 (1)结构定义 (2)基本函数 (3)操作实现 测试 代码 前言 链表的类型有很多种(根据带头或不带头,循环或非循环等等),但是我们重点研究的只有两种,一种结构非常简单是无头单向 ...

  5. 试编写一个将双向循环链表逆置的算法_图解:链表的快慢指针,解决 80% 的链表面试题!...

    一.前言 链表是基本的数据结构之一,它与数组不同,数组在内存中存储,需要一块连续的内容空间来存储,对内存的要求比较高.例如我们需要 100MB 大小的数组,内存中就必须有一段连续的 100MB 的内存 ...

  6. C语言线性表之双向循环链表

    #include<stdio.h> #include<stdlib.h>/* 结构体:双向循环链表 */ typedef struct DuLNode{int data;str ...

  7. 《恋上数据结构第1季》单向循环链表、双向循环链表以及约瑟夫环问题

    循环链表(CircleList) 链表的接口设计 单向循环链表 单向循环链表完整源码 双向循环链表 双向循环链表完整源码 双向循环链表解决约瑟夫环问题 如何发挥循环链表的最大威力? 静态链表 数据结构 ...

  8. 算法不会,尚能饭否之双向循环链表

    嗨,朋友们,你懂得,写篇博文不容易! 这次写的这个篇博文是关于双向循环链表.呵呵,双向链表,只要你知道其中任何一个节点的地址,就可以遍历表中其它任何一个节点.不错吧.不错的数据结构,没事,自己写了一个 ...

  9. 详解Linux内核之双向循环链表 By邪恶八进制

    [转载]详解Linux内核之双向循环链表 详解Linux内核之双向循环链表 信息来源:邪恶八进制信息安全团队(www.eviloctal.com) 摘要:      本文详解了内核中面向对象的list ...

最新文章

  1. Linux ubuntu中怎么生成随机数,随机数的生成
  2. java内存 phd文件抓取_您可以从IBM PHD Java堆转储中提取字符串的值吗?
  3. 2021年武大CS\南大CS\哈工CS\浙软\西交CS\天大佐治亚CS\中科院信网中心面试经验贴
  4. java nlpir_中科院NLPIR中文分词java版
  5. 软件测试常见笔试面试题(二)
  6. 二本院校女毕业生,想去北漂,求建议
  7. WPF中的附加行为简介
  8. java.lang.ClassNotFoundException: com.sun.xml.ws.spi.ProviderImpl解决办法
  9. WCF后传系列(2):深入WCF寻址Part 2—自定义寻址报头
  10. Python模块的导入
  11. zabbix重点笔记
  12. 无极浏览器(教学专用浏览器)官方版 v5.0.0.15
  13. Python解答蓝桥杯省赛真题之从入门到真题
  14. mysql中key的用法_数据库中KEY的用法
  15. python熊猫弹幕_python奇闻杂技05 爬虫初步学习+jieba分词+词云库+哔哩哔哩弹幕爬取示例(数据分析pandas)...
  16. win7下运行.php,Win7下在IIS7中配置PHP的FastCGI支持_笔记
  17. 属性基加密仿真及代码实现(CP-ABE)论文:Ciphertext-Policy Attribute-Based Encryption
  18. wps不能打印_除了office/wps,还有一些好用的办公软件推荐给你
  19. C#下Winform下使用WebKit、Geckofx、CefSharp对比及CefSharp代码实现
  20. git时出现rejected

热门文章

  1. Java进程CPU占用高导致的网页请求超时的故障排查
  2. JeecgBoot 2.4 微服务正式版发布,基于SpringBoot的低代码平台
  3. jeecg 3.7.1 新版功能,集群定时任务动态发布模块 使用规则
  4. 动态表单及动态建表实现原理
  5. “无法找到运行搜索助理需要的一个文件”的解决办法
  6. Socket编程实践(2) --Socket编程导引
  7. RedHat系列软件管理(第二版) --二进制软件包管理
  8. iOS 后台语音播报功能开发过程中的那些坑
  9. 大疆地理围栏系统预防无人机闯入机场
  10. Linux,没你想象的那么安全!