二、【数据结构】列表(list)的实现

本文使用c++实现list数据结构,list的接口函数采用高效的实现方式,这样一方面使我加深对数据结构的理解,另一方便可以让我再复习复习c++,通过前几天写的vector数据结构的底层实现,我确实又进一步地熟悉使用C++进行编程,,这次写list的实现过程中,我几乎没有怎么查看《c++prime》了哈哈,就是函数对象形式的遍历函数的声明格式怎么也想不起来,后来查书才明白函数的形参其实是个类的对象,只不过这个类名要在声明前指明,如下:

template<typename FuncClass> void traverse(FuncClass func);

list的实现包含两个类:listNodelist,其中listNode中主要描述了list中单个节点的内部结构,包含一个data变量和两个分别指向前节点和后节点的指针;而list类则是描述了一个list的结构及其操作,比如查看规模大小、插入新节点、删除节点、排序、查找等。

listNode接口列表
操作功能对象
listNode()默认构造函数 
listNode(T e, listNode<T> *p, listNode<T> *s)构造函数,设置data,指向前后节点的指针 
~listNode析构函数 
insertAsPred(const T& e)在当前节点前插入一个新节点节点
insertAsSucc(const T& e)在当前节点后插入一个新节点节点
list接口列表
操作功能对象
list()默认构造函数,只初始化list的首尾哨兵节点 
list(std::initializer_list<T> li)构造函数(列表初始化方式) 
list(listNode<T>* p, int n)构造函数,拷贝指定节点及其后n个节点 
list(list<T>& li)构造函数,拷贝另一list对象 
list(list<T>& li, Rank lr, Rank rr)构造函数,拷贝另一list对象的指定区间 
~list()析构函数,手动释放哨兵及有效节点的内存空间 
init()list初始化时创建前后哨兵节点列表
size()返回list对象的规模列表
display()打印当前list中的所有元素列表
first()返回第一个有效节点的地址列表
last()返回最后一个有效节点的地址列表
find(const T& e, int n, listNode<T>* p)在节点p之前的n个长度范围内查找元素列表
find(const T& e)在整个list中查找元素列表
search(const T& e, int n, listNode<T>* p)在节点p之前的n个长度范围内查找元素e,返回不大于此元素的最大节点的地址有序列表
search(const T& e)在整个list中查找元素,返回不大于此元素的最大节点的地址有序列表
insertAsFirst(const T& e)插入元素作为first节点列表
insertAsLast(const T& e)插入元素作为last节点列表
insertAsPred(listNode<T>* p, const T& e)在节点P之前插入元素e列表
insertAsSucc(listNode<T>* p, const T& e)在节点P之后插入元素e列表
insert(Rank r, const T& e)在指定秩出插入元素(警告:线性复杂度)列表
remove(listNode<T>* p)删除指定节点列表
clear()清除list内所有有效节点列表
deduplicate()去除list内重复元素列表
uniquify()去除list内重复元素有序列表
traverse(void(*func)(T &))批量处理list内所有元素(函数指针方式)列表
traverse(FuncClass func)批量处理list内所有元素(函数对象方式)列表
sort(listNode<T>* p, int n,int s)排序接口汇总列表
insertionSort()插入排序法列表
insertionSort(listNode<T>* p,int n)对从p节点开始的n范围内的节点进行排序(插入排序法)列表
selectionSort()选择排序法列表
selectionSort(listNode<T>* p, int n)对从p节点开始的n范围内的节点进行排序(选择排序法)列表
mergeSort(listNode<T>* p,int n)对从p节点开始的n范围内的节点进行排序(归并排序法)列表
重载运算符[]下标运算符列表
重载运算符=赋值运算符(列表赋值方式)列表

(1) listNode.h

#pragma once
typedef int Rank;


template<typename T> struct listNode   //节点元素模板类
{
	//成员变量
	T data;
	listNode<T> *pred, *succ;    //定义前驱和后继指针,实现双向链表

	//构造函数
	listNode() {}     //构造list前后哨兵节点用
	listNode(T e, listNode<T> *p = nullptr, listNode<T> *s = nullptr) :data(e), pred(p), succ(s) {}
	//析构函数
	~listNode(){}

	//成员函数
	listNode<T>* insertAsPred(const T& e);  //在当前节点前插入一个新节点
	listNode<T>* insertAsSucc(const T& e);  //在当前节点后插入一个新节点
};

template<typename T> listNode<T>* listNode<T>::insertAsPred(const T& e)
{
	listNode<T> *p = new listNode<T>(e, pred, this);    //更新4个指针的指向
	pred->succ = p;
	pred = p;
	return p;
}

template<typename T> listNode<T>* listNode<T>::insertAsSucc(const T& e)
{
	listNode<T> *p = new listNode<T>(e, this, succ);
	succ->pred = p;
	succ = p;
	return p;
}

(2) list.h

#pragma once
#include "listNode.h"
typedef int Rank;

template<typename T> class list         //list结构:  [sentinel node]--[[first]...[]....[last]]--[sentinel node]
{
protected:                    
	int _size;    //list规模
	listNode<T> *header, *trailer;      //list的前后哨兵节点的指针

public:
	//构造函数
	list() { init(); }
	list(std::initializer_list<T> li);  //列表初始化构造方式
	list(listNode<T>* p, int n);        //拷贝构造,拷贝节点p及其后n个范围内的所有节点
	list(list<T>& li) :list(li.header, li._size) {}    //拷贝构造,拷贝整个list对象
	list(list<T>& li, Rank lr, Rank rr);  //拷贝构造,拷贝指定list对象的指定区间
	//析构函数(只需要手动处理new的对象)
	~list();

	//普通成员函数
	void init();    //list初始化时创建前后哨兵节点,_size置0
	int size();     //返回list对象的规模
	void display(); //打印当前list中的所有元素
	listNode<T>* first();             //返回第一个有效节点的地址
	listNode<T>* last();              //返回最后一个有效节点的地址
	listNode<T>* find(const T& e, int n, listNode<T>* p); //在节点p之前的n个长度范围内查找元素e
	listNode<T>* find(const T& e);                        //查找元素e
	listNode<T>* search(const T& e, int n, listNode<T>* p); //在节点p之前的n个长度范围内查找元素e(要求list为有序序列,返回不大于此元素的最大节点的指针)	
	listNode<T>* search(const T& e);         //查找元素e(要求list为有序序列,返回不大于此元素的最大节点的指针)
	listNode<T>* insertAsFirst(const T& e);  //插入元素作为first节点
	listNode<T>* insertAsLast(const T& e);   //插入元素作为last节点
	listNode<T>* insertAsPred(listNode<T>* p, const T& e);  //在节点P之前插入元素e
	listNode<T>* insertAsSucc(listNode<T>* p, const T& e);  //在节点P之后插入元素e
	listNode<T>* insert(Rank r, const T& e);                //在指定秩出插入元素(警告:线性复杂度)
	T remove(listNode<T>* p);          //删除指定节点
	int clear();		 //清除list内所有有效节点
	int deduplicate();   //去除list内重复元素
	int uniquify();      //去除list内重复元素(要求list为有序序列)
	void traverse(void(*func)(T &));		    //批量处理list内所有元素(函数指针方式)
	template<typename FuncClass> void traverse(FuncClass func);	//批量处理list内所有元素(函数对象方式)
	void sort(listNode<T>* p, int n,int s);           //排序接口汇总
	void insertionSort();        //插入排序法
	void insertionSort(listNode<T>* p,int n);   //对从p节点开始的n范围内的节点进行排序
	void selectionSort();        //选择排序法
	void selectionSort(listNode<T>* p, int n);  //对从p节点开始的n范围内的节点进行排序
	void mergeSort(listNode<T>* p,int n);       //归并排序法
	//重载运算符
	T& operator[](Rank r);  //下标运算符重载
	list<T>& operator=(const list<T>& li); //赋值运算符重载
};

template<typename T> void list<T>::init()
{
	header = new listNode<T>();     //创建前后哨兵节点
	trailer = new listNode<T>();
	_size = 0;
	header->succ = trailer;         //设置指针指向
	header->pred = nullptr;
	trailer->pred = header;
	trailer->succ = nullptr;
}

template<typename T> list<T>::list(std::initializer_list<T> li)
{
	init();   
	listNode<T> *p=header;
	for (auto iter = li.begin(); iter != li.end(); iter++)
	{
		p = p->insertAsSucc(*iter);
		_size++;
	}
}

template<typename T> list<T>::list(listNode<T>* p, int n)
{
	init();
	listNode<T> *ptr=header;
	while (n--)
	{	
		ptr=ptr->insertAsSucc(p->data);
		p = p->succ;
		_size++;
	}

}

template<typename T> list<T>::list(list<T>& li, Rank lr, Rank rr)
{
	init();
	listNode<T>* p = li.first();
	listNode<T>* ptr = header;
	for (int i = 0; i < rr; i++)
	{
		if (i < lr)
			p = p->succ;
		else
		{
			ptr = ptr->insertAsSucc(p->data);
			p = p->succ;
			_size++;
		}
	}
}

template<typename T> list<T>::~list()
{
	clear();   //清除所有有效节点
	delete header;
	delete trailer;
}

template<typename T> void list<T>::display()
{
	listNode<T>* p = header;
	cout << "size:" << _size << endl;
	if (_size)
	{
		for (Rank r = 0; r < _size; r++)
		{
			p = p->succ;
			(r < (_size - 1)) ? cout << p->data << "," : cout << p->data;
		}
		cout << endl;
	}
}

template<typename T> int list<T>::size()
{
	return _size;
}

template<typename T> listNode<T>* list<T>::find(const T& e, int n, listNode<T>* p)    //包含p节点,n>1才能搜索
{
	while ((n--)&&(p!=header))  //已经遍历n次或则到达header
	{
		if (p->data == e)
			return p;
		else
			p = p->pred;
	}
	return nullptr;
}

template<typename T> listNode<T>* list<T>::find(const T& e) 
{
	return find(e, _size - 1, last());
}

template<typename T> listNode<T>* list<T>::search(const T& e, int n, listNode<T>* p)   //包含p节点,n>1才能搜索
{
	while ((n--) && (p != header))
	{
		if (p->data <= e) //返回不大于指定元素的最大节点,方便在其后面插入
			return p;
		else
			p = p->pred;	
	}
	return p;
}


template<typename T> listNode<T>* list<T>::search(const T& e)
{
	return search(e, _size + 1, last());
}

template<typename T> listNode<T>* list<T>::first()
{
	return header->succ;
}

template<typename T> listNode<T>* list<T>::last()
{
	return trailer->pred;
}

template<typename T> T& list<T>::operator[](Rank r)
{
	listNode<T>* p=header->succ;
	while (r-->0)   
	{
		p = p->succ;
	}
	return p->data;
}

template<typename T> listNode<T>* list<T>::insertAsFirst(const T& e)
{
	_size++;
	listNode<T> *p = header->insertAsSucc(e);   //函数内部已经更新了4个指针指向
	return p;
}

template<typename T> listNode<T>* list<T>::insertAsLast(const T& e)
{
	_size++;
	listNode<T> *p = trailer->insertAsPred(e);
	return p;
}

template<typename T> listNode<T>* list<T>::insertAsPred(listNode<T>* p, const T& e)
{
	_size++;
	return p->insertAsPred(e);
}

template<typename T> listNode<T>* list<T>::insertAsSucc(listNode<T>* p, const T& e)
{
	_size++;
	return p->insertAsSucc(e);
}

template<typename T> listNode<T>* list<T>::insert(Rank r, const T& e)
{
	listNode<T> *p=header;
	while (r--)
	{
		p = p->succ;
	}
	return insertAsSucc(p, e);
}

template<typename T> T list<T>::remove(listNode<T>* p)
{	
	T e = p->data;
	p->pred->succ = p->succ;
	p->succ->pred = p->pred;
	_size--;
	delete p;
	return e;
}

template<typename T> int list<T>::clear()
{
	int oldSize = _size;
	while (header->succ != trailer)
		remove(header->succ);
	return oldSize;
}

template<typename T> int list<T>::deduplicate()
{
	if (!_size) return 0;
	int n = 0;
	listNode<T>* p = header->succ;
	listNode<T>* lp;  //缓存p的前一个元素
	for (int i = 0; i < _size;)
	{
		lp = p->pred;
		if (find(p->data, _size, p->pred))   //在当前元素之前寻找,越界则退出
		{
			remove(p);n++;
			p = lp->succ;
		}
		else
		{
			i++; 
			p = p->succ;
		}
	}
	return n;
}

template<typename T> int list<T>::uniquify()
{
	if (!_size) return 0;
	int oldSize = _size;
	listNode<T> *p = header->succ;
	while (p->succ!=trailer)   //队尾越界停止
	{
		if (p->data == p->succ->data)
			remove(p->succ);
		else
			p = p->succ;		
	}
	return oldSize - _size;
}


template<typename T> void list<T>::traverse(void(*func)(T &))
{
	for (Rank r = 0; r < _size; r++)
		func((*this)[r]);
}

template<typename T> template<typename FuncClass> void list<T>::traverse(FuncClass func)
{
	for (Rank r = 0; r < _size; r++)
		func((*this)[r]);
}

template<typename T> list<T>& list<T>::operator=(const list<T> &li)
{
	clear();  //清空有效节点
	if (!li._size) return *this;
	listNode<T>* p = li.header;
	listNode<T>* lp = header;

	while ((p = p->succ) != li.trailer)
	{
		lp->insertAsSucc(p->data);
		lp = lp->succ;
		_size++;
	}
	return *this;
}

template<typename T> void list<T>::sort(listNode<T>* p, int n, int s)
{
	switch (s)
	{
	case 0:
		insertionSort(p, n); break;
	case 1:
		selectionSort(p, n); break;
	case 2:
		mergeSort(p, n); break;
	default:
		break;
	}
}

template<typename T> void list<T>::insertionSort()
{
	if (_size < 2) return;
	listNode<T> *p = header->succ;
	while (p != trailer)   //列尾溢出则终止
	{
		search(p->data, _size+1, p->pred)->insertAsSucc(p->data);
		_size++;
		p = p->succ;
		remove(p->pred);
	}
}

template<typename T> void list<T>::insertionSort(listNode<T>* p, int n)
{
	if (n < 2) return;
	int s = 0;
	while ((n--) && (p != trailer))   //变量n次或列尾溢出则终止
	{
		search(p->data, s, p->pred)->insertAsSucc(p->data);
		_size++;
		p = p->succ;
		remove(p->pred);
		s++;
	}
}

template<typename T> void list<T>::selectionSort()
{
	if (_size < 2) return;
	listNode<T> *p = first();
	listNode<T> *ptr;   //缓存待删除的节点指针
	for (int i = 0; i < _size; i++)   //_size次迭代
	{
		T min = first()->data;
		p = first();
		ptr = p;
		for (int j = 0; j < _size - i; j++)   //内循环找最小值并插入到last位置(保证排序稳定)
		{
			if ((p->data) <= min)
			{
				min = p->data;
				ptr = p;
			}
			p = p->succ;
		}
		remove(ptr);
		insertAsLast(min);
	}
}

template<typename T> void list<T>::selectionSort(listNode<T>* p, int n)
{
	if (n < 2) return;
	p = p->pred;
	listNode<T> *pp = p->succ;  //迭代指针
	listNode<T> *ptr;			//缓存待删除的节点指针
	listNode<T> *trail = p;		//排序区间的最后一个元素,即排序区间为(p->pred,trail)
	for (int i = 0; i < n+1; i++)
		trail = trail->succ;
	for (int i = 0; i < n; i++)			  //n次迭代
	{
		T min = (p->succ)->data;
		pp = p->succ;
		ptr = p->succ;
		for (int j = 0; j < n - i; j++)   //内循环找最小值并插入到trail位置(保证排序稳定)
		{
			if ((pp->data) <= min)
			{
				min = pp->data;
				ptr = pp;
			}
			pp = pp->succ;
		}
		remove(ptr);
		trail->insertAsPred(min);
		_size++;
	}
}

template<typename T> void list<T>::mergeSort(listNode<T>* p, int n)    //[p,p_n)
{
	if (n < 2) return;
	//开始分裂
	listNode<T>* ppred = p->pred;  //缓存待排序list的前哨兵
	listNode<T>* pmi = p;  //计算中间节点
	for (int i = 0; i < (n >> 1); i++)       //[p0,p1,p2] n=3 ==>  [p0] [p1,p2]
	{
		pmi = pmi->succ;
	}
	mergeSort(p, n >> 1);         //这两句递归语句表示已分离的两个子序列均已经排序完成
	mergeSort(pmi, n - (n >> 1));

	//开始归并(两个有序短序列==》一个有序长序列)  [pred][AAAAAAAAA][BBBBBBBBB]

	//更新各端点的地址(在递归时插入和删除改变了逻辑顺序节点的实际物理地址)
	p = ppred->succ;
	pmi = p;  //计算中间节点
	for (int i = 0; i < (n >> 1); i++)      
	{
		pmi = pmi->succ;
	}
	for (Rank i = (n >> 1), j = (n - (n >> 1)); i || j;)
	{
		if ((i > 0) && (j == 0))   //只剩下前段list
		{	
			i--;
			ppred->insertAsSucc(p->data);
			ppred = ppred->succ;
			_size++;
			p = p->succ;
			remove(p->pred);
		}
		if ((j > 0) && (i == 0))    //只剩下后段list
		{
			j--;
			ppred->insertAsSucc(pmi->data);
			ppred = ppred->succ;
			_size++;
			pmi = pmi->succ;
			remove(pmi->pred);
		}
		if ((i > 0) && (j > 0))     //两段list都有值,则选择最小的插在前面
		{
			if ((p->data) < (pmi->data))
			{
				i--;
				ppred->insertAsSucc(p->data);
				ppred = ppred->succ;
				_size++;
				p = p->succ;
				remove(p->pred);
			}
			else
			{
				j--;
				ppred->insertAsSucc(pmi->data);
				ppred = ppred->succ;
				_size++;
				pmi = pmi->succ;
				remove(pmi->pred);
			}
		}
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值