您的位置:首页 > 编程语言 > C语言/C++

浅谈STL list<T>链表容器和迭代器的使用C++实现

2017-05-26 21:46 826 查看
    一、今天简单的实现了STL容器里面的顺序容器list双链表里面的简单应用和迭代器的简单实现方法

   包括迭代器的重载方法

    二、双向链表的实现需要了解 堆得内存分配问题。堆内存是开发者使用new开辟的空间 需要开发者自己释放掉内存 否者将会存在内存中知道程序结束

   所以对内存的释放很重要。当了解了堆和栈的分配之后将会更加容易理解链表的节点的实现方法。

  三、关于栈内存的分配将会在博客中发布

    

   

using namespace std;

template
class STL_List
{
public:
STL_List();
//list链表指针结构体
template
struct Nope
{
T data;
Nope *front;
Nope *next;
//构造函数
Nope() :data(T()), front(nullptr), next(nullptr) {}
Nope(const T &data) :front(nullptr), next(nullptr)
{
this->data = data;
}
};
//迭代器类
class Iterator
{
public:
Iterator() {}
Iterator(Nope * &p)
{
head = p;
}
//复制构造函数
Iterator(Iterator & object)
{
this->head =object.head ;
}

//重载前置自增
Iterator operator++()
{
head = head->next;
return *this;
}
//后置自增    区分前置和后置 后置函数参数列表 多了个(int)
Iterator operator++(int)
{
Iterator temp(*this);
head = head->next;
return temp;
}

//重载输出内容
friend  T operator*(Iterator &it)   //重载*用friend
{
return  it.head->data;
}

friend  bool  operator!=(Iterator &it, Iterator &it1)
{
if (it.head!= it1.head)
{
return true;
}

return false;

}

private:
Nope *head;
};

//后插
void push_back(const T &n_data);

//前插
void push_front(const T &n_data);

//删除指定的值 为空时删除失败
bool remove(T a);

//找到返回 true
Nope * Search(T a);

//返回头结点位置的迭代器对象
Iterator begin() { return Iterator(head); } //通过返回Iterator类型  直接调用构造函数

//返回尾节点 迭代器对象
Iterator end() { return Iterator(tail->next); }  //返回节点最后一位的后一个空指针

//摧毁链表释放内存
bool Destroy();

//测试的函数 运用指针的遍历 只适用于编译器内置类型 不能用于自己开发的类和结构体
void show()
{
Nope *p = head;
if (p==nullptr)
return;
while (p)
{
cout << p->data << endl;
p = p->next;
}
}

~STL_List();
private:
Nope *head;
Nope *tail;
//利用一个简便的函数自己分配 堆内存空间  Nope *&p 形参使用引用 直接修改调用该函数的指针指向位置无需返回值
bool New_n(Nope *&p, const T &data)
{
p = new Nope(data);
return true;
}
};

template
STL_List::STL_List()
{
head = nullptr;
tail = nullptr;
}

template
void STL_List::push_back(const T &n_data)
{
Nope *temp;
New_n(temp,n_data);  //分配堆空间
//如果链表为空
if (!head)
{
head = temp;
tail = temp;
return ;
}
//不为空时 雷同 push_front();
tail->next = temp;
temp->front = tail;
tail = temp;
return;
}
template
void STL_List::push_front(const T & n_data)
{
Nope *temp;
New_n(temp, n_data);
//如果头结点为空 链表为空
if (nullptr == tail)
{
head = temp;
tail = temp;
return;
}
//链表中有元素时
head->front = temp; //将当前头指针前面指针储存为temp
temp->next = head;//将temp的后一个节点(也就是temp->next) 指向头指针
head = temp;  //跟新头指针到temp的位置

}

template
bool STL_List::remove(T a)
{
Nope *temp= Search(a); //找到删除的指针

if (temp == head)
{
head = temp->next;
head->front = nullptr;
delete temp;
return true;
}
else if (temp == tail)
{
tail = temp->front;
tail->next=nullptr;  //重新让为指针next为空 防止打印时检测不到NULL触发异常
delete temp;
return true;
}
else
{
Nope *p = temp;
temp->front->next = temp->next;
temp->next->front = temp->front;
delete p;
return true;
}

return false;
}
template
typename  STL_List::Nope * STL_List::Search(T a)  //前面加上typename将不会产生错误 因为这样编译器才会将
{                                                          //STL_List::Nope * 认定为类型即 Nope*(结构体指针类型)
Nope *p = head;   //创建临时变量进行遍历不会影响到 类中私人数据head节点
if (!head)
return NULL;
//遍历并进行查找
while (p)
{
if (p->data == a)
{
return p;   // 返回 (Nope*) 结构体指针类型
}
p = p->next;
}

return NULL;
}
template
bool STL_List::Destroy()
{
Nope *temp = head;

if (!temp)
return true;
Nope *p = nullptr;  //删除节点指针临时变量
while (temp)
{

p = temp;
temp = temp->next;
delete p;
}
if (!temp)
{
head = nullptr;
tail = nullptr;
return true;
}
else

return false;
}
template
STL_List::~STL_List()
{

Destroy();  //删除自己使用 new 分配的堆空间 释放内存

}


下面是测试代码
#include
//#include
#include "STL_List.h"
#include
using namespace std;

int main()
{
STL_List a;
STL_List::Iterator itr;//::表示作用域 表示class Iterator 类在STL_List类里面 是其成员内部类

a.push_back(22);
a.push_back(33);
a.push_back(44);
a.push_front(77);
a.push_front(88);
itr = a.begin();
for (; itr != a.end(); ++itr)
{
cout << *itr << endl;
}

//a.show();
//a.remove();
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 数据结构 stl list
相关文章推荐