您的位置:首页 > 大数据 > 人工智能

模板(双向链表与队列)

2016-03-20 20:48 447 查看
”双向链表与队列“

“双向链表”是包含两个指针域,一个数据域,既有指向前驱的指针,还有指向后继的指针,同时可以从两个方向对链表进行遍历,访问各个节点。“双向链表”较”单链表“在插入和删除节点方面更为简单,但是所占的空间比“单链表”大。“队列”的实现之所以选择使用双向链表,是因为队列的特点是“先进先出”,如若使用顺序表则很大程度上的浪费空间。在这样的情境下,链表较顺序表更为合适。

根据“模板”的概念,设计并实现双向链表,进而实现队列的基本功能。下面是利用模板来实现双向链表的具体代码:

#pragma once
#include <assert.h>

//双向链表
template <class T>
struct ListNode
{
T _data;
ListNode<T> * _next;
ListNode<T> * _prev;
ListNode(const T& x)
:_data(x)
, _next(NULL)
, _prev(NULL)
{ }
};

template <class T>
class List
{
public:
List()    //构造函数
:_head(NULL)
, _tail(NULL)
{ }

~List()   //析构函数
{
Clear();
}

public:
void pushBack(const T & x)     //尾插
{
if (_head == NULL)
{
_head = _tail = new ListNode<T>(x);
}
else
{
ListNode<T> * tmp = new ListNode<T>(x);
_tail->_next = tmp;
tmp->_prev = _tail;
_tail = tmp;
tmp->_next = NULL;
}
}

void popBack()    //尾删
{
if (_head == NULL)
{
return;
}
else if (_head == _tail)
{
delete _tail;
_head = _tail = NULL;
}
else
{
ListNode<T> * tmp = _tail->_prev;
delete _tail;
tmp->_next = NULL;
_tail = tmp;
}
}

void pushFront(const T & x)     //头插
{
ListNode<T> * tmp = new ListNode<T>(x);
if (_head == NULL)
{
_head = _tail = tmp;
}
else
{
tmp->_next = _head;
tmp->_prev = NULL;
_head = tmp;
}
}

void popFront()     //头删
{
if (_head == _tail)
{
if (_head)
{
delete _head;
_head = _tail = NULL;
}
}
else
{
ListNode<T> * tmp = _head->_next;
delete _head;
_head = tmp;
tmp->_prev = NULL;
}
}

void Insert(ListNode<T> * pos,const T& x)    //在pos位置上插入数据x
{
assert(pos);
ListNode<T> * tmp = new ListNode<T>(x);
ListNode<T> * cur = pos->_next;
tmp->_next = cur;
cur->_prev = tmp;
tmp->_prev = pos;
pos->_next = tmp;
}

void Erase(ListNode<T> * pos)    //删除pos位置上的数据
{
assert(pos);
if (_head == NULL)
{
return;
}
else if (_head == _tail)
{
delete _head;
}
else
{
ListNode<T> * cur = pos->_next;
ListNode<T> * tmp = pos->_prev;
tmp->_next = cur;
cur->_prev = tmp;
delete pos;
}
}

ListNode<T> * Find(const T & x)     //查找
{
ListNode<T> * tmp = _head;
while (tmp)
{
if (tmp->_data == x)
{
return tmp;
}
tmp = tmp->_next;
}
if (tmp->_next)
{
return NULL;
}
}

T & Top()     //读取队头元素
{
return _head->_data;
}

T & Back()     //读取队尾元素
{
assert(size > 0);
return _tail->_data;
}

void Reverse()     //逆置
{
swap(_head, _tail);
ListNode<T>* tmp = _head;
while (tmp)
{
swap(tmp->_prev, tmp->_next);
tmp = tmp->_next;
}
}

void Sort()      //冒泡排序
{
ListNode<T> * cur = _head;
ListNode<T> * tmp = _head->_next;
while (tmp)
{
if (cur->_data > tmp->_data)
{
T ptr = cur->_data;
cur->_data = tmp->_data;
tmp->_data = ptr;
}
cur = cur->_next;
tmp = tmp->_next;
}
}

void Unique()    //在有序链表中,去掉重复的数据
{
ListNode<T> * cur = _head;
ListNode<T> * tmp = _head->_next;
while (tmp)
{
while (cur->_data == tmp->_data)
{
ListNode<T>* str = tmp;
tmp = tmp->_next;
Erase(str);
}
cur = cur->_next;
tmp = tmp->_next;
}
}

void Merge(List<T> & s)    //将某一个链表连接到这个链表后面
{
_tail->_next = s._head;
s._head->_prev = _tail;
}

void Splice(ListNode<T> * pos, List<T> & s)    //将一个链表连接到pos位置后面
{
assert(pos);
if (pos == _tail)
{
Merge(s);
}
else
{
ListNode<T> *  cur = pos;
ListNode<T> * tmp = pos->_next;
ListNode<T> * str = s._tail;
cur->_next = s._head;
s._head->_prev = cur;
str->_next = tmp;
tmp->_prev = str;
}
}

size_t Size()    //计算链表中的元素个数
{
ListNode<T> * tmp = _head;
int count = 0;
while (tmp)
{
count++;
tmp = tmp->_next;
}
return count;
}

void print()   //格式输出
{
ListNode<T> * tmp = _head;
while (tmp)
{
cout << tmp->_data << " ";
tmp = tmp->_next;
}
cout << endl;
}

void Clear()
{
ListNode<T> * tmp = _head;
while (tmp)
{
ListNode<T> * str = tmp;
tmp = tmp->_next;
delete str;
}
}

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


对于”队列“能够利用上述双向链表的功能来实现,下面就是基本的程序代码:

#pragma once
#include <string>

//队列
#include <assert.h>
#include "ListNode.h"
template <class T , template<class> class container = List>
class Queue
{
public:
void push(const T & x)   //进入队列
{
_con.pushBack(x);
}

void pop()         //出队列
{
_con.popFront();
}

bool Empty()    //判断队列是否为空
{
return _con.Size() == 0;
}

size_t size()    //计算队列中的元素个数
{
return _con.size();
}

T & top()    //队头节点
{
return _con.Top();
}

T & Back()    //队尾节点
{
return _con.Back();
}

void print()    //格式输出
{
_con.print();
}

private:
container<T> _con;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息