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

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

template void traverse(FuncClass func);

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

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

(1) listNode.h

#pragma once
typedef int Rank;


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

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

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

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

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

(2) list.h

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

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

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

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

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

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

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

}

template list::list(list& li, Rank lr, Rank rr)
{
	init();
	listNode* p = li.first();
	listNode* 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 list::~list()
{
	clear();   //清除所有有效节点
	delete header;
	delete trailer;
}

template void list::display()
{
	listNode* 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 int list::size()
{
	return _size;
}

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

template void list::insertionSort(listNode* 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 void list::selectionSort()
{
	if (_size < 2) return;
	listNode *p = first();
	listNode *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 void list::selectionSort(listNode* p, int n)
{
	if (n < 2) return;
	p = p->pred;
	listNode *pp = p->succ;  //迭代指针
	listNode *ptr;			//缓存待删除的节点指针
	listNode *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 void list::mergeSort(listNode* p, int n)    //[p,p_n)
{
	if (n < 2) return;
	//开始分裂
	listNode* ppred = p->pred;  //缓存待排序list的前哨兵
	listNode* 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);
			}
		}
	}
}

 

你可能感兴趣的:(数据结构)