注意:本章节《C++数据结构具体实现》均转载自博客:https://blog.csdn.net/qq_23912545/article/category/6868003
本章节的所有代码均是博主前面几篇博客的参考,C++及数据结构复习笔记(十一~十二)的参考,可以说是前面所讲数据结构时,对所有模板类以及ADT接口的一个整合。可以辅助大家对于数据结构具体实现的理解。其中有很大一部分是我在前面的博客中没有讲到的,读者可以根据自己的情况决定是否精进。
#ifndef VECTOR_H
#define VECTOR_H
#include "Fib.h"
typedef int Rank;//秩
#define DEFAULT_CAPACITY 3 //默认的初始容量
template class Vector{ //向量模板类
protected:
Rank _size; int _capacity; T* _elem;//规模、容量、数据区
void copyFrom(T const *A, Rank lo, Rank hi);//复制数组区间A[lo,hi)
void expand();//空间不足时扩容
void shrink();//装填因子过小时压缩
Rank bubble(Rank lo, Rank hi);//扫描交换
void bubbleSort(Rank lo, Rank hi);//起泡排序算法
Rank max(Rank lo, Rank hi);//选取最大元素
void selectionSort(Rank lo, Rank hi);//选择排序算法
void merge(Rank lo, Rank mi, Rank hi);//归并算法
void mergeSort(Rank lo, Rank hi);//归并排序算法
Rank partition(Rank lo, Rank hi);//轴点构造算法
void quickSort(Rank lo, Rank hi);//快速排序算法
void heapSort(Rank lo, Rank hi);//堆排序
public:
//构造函数
Vector(int c = DEFAULT_CAPACITY,int s = 0 ,T v = 0){ //容量为c,规模为s,所有元素初始化v
_elem = new T[_capacity = c];
for (_size = 0; _size < s; _elem[_size++] = v);//s<=c
}
Vector(T const *A, Rank n){//数组整体复制
copyFrom(A, 0, n);
}
Vector(T const *A, Rank lo, Rank hi){//数组区间
copyFrom(A, lo, hi);
}
Vector(Vector const& V, Rank lo, Rank hi){//向量区间
copyFrom(V._elem, lo, hi);
}
Vector(Vector const& V){//向量整体复制
copyFrom(V._elem, 0, v._size);
}
//析构函数
~Vector(){
delete[] _elem;//释放空间
}
//只读访问接口
Rank size() const{ return _size; }//规模
bool empty() const{ return !_size; }//判空
int disordered() const;//判断向量是否已排序
Rank find(T const& e) const { return find(e, 0, _size); }//无序向量整体查找
Rank find(T const &e, Rank lo, Rank hi) const;//无序向量区间查找
Rank search(T const& e) const{//有序向量整体查找
return(0 >= _size) ? -1 : search(e, 0, _size);
}
Rank search(T const& e, Rank lo, Rank hi) const;//有序向量区间查找
//可写访问接口
T& operator[] (Rank r) const;//重载下标操作符
Vector & operator= (Vector const&); //重载赋值操作符以便于克隆向量
T remove(Rank r);//删除秩为r的元素
int remove(Rank lo, Rank hi);//删除秩在区间[lo,hi)之内的元素
Rank insert(Rank r, T const& e);//插入元素
Rank insert(T const& e){ return insert(_size, e); }//默认作为末元素插入
void sort(Rank lo, Rank hi);//对[lo,hi)排序
void sort(){ sort(0, _size); }//整体排序
void unsort(Rank lo, Rank hi);//对[lo,hi)置乱
void unsort(){ unsort(0, _size); }//整体置乱
int deduplicate();//无序去重
int uniquify();//有序去重
//遍历
void traverse(void(*visit)(T&));//遍历(使用函数指针,只读或者局部性修改)
template void traverse(VST&);//遍历(使用函数对象,可全局性修改)
};
//函数定义
template
void Vector::copyFrom(T const *A, Rank lo, Rank hi){
_elem = new T[_capacity = 2 * (hi - lo)];//分配空间
_size = 0;//规模清零
while (lo < hi)//[lo,hi)内的元素逐一
_elem[_size++] = A[lo++];//复制到_elem[0,hi-lo)
}
template
void Vector::expand(){
if (_size < _capacity) return;//尚未满员,不必扩容
if (_capacity < DEFAULT_CAPACITY)_capacity = DEFAULT_CAPACITY;//不低于最小容量
T* oldElem = _elem;
_elem = new T[_capacity <<= 1];//容量倍增
for (int i = 0; i < _size; i++)
_elem[i] = oldElem[i];//T为基本类型,或者已经重载复制操作符"="
delete[] oldElem;//释放原空间
}
template
Rank Vector::insert(Rank r, T const& e){//插入操作
expand();//若有必要扩容
for (int i = _size; i > r; i--)//自后向前
_elem[i] = _elem[i - 1];
_elem[r] = e; _size++; return r;//置入新元素,更新容量,返回秩
}
template
void Vector::traverse(void(*visit)(T &)){//利用函数指针机制,只读或者局部性修改
for (int i = 0; i < _size; i++)
visit(_elem[i]);//遍历向量
}
template template
void Vector::traverse(VST& visit){//借助函数对象机制
for (int i = 0; i < _size; i++)
visit(_elem[i]);//遍历向量
}
template
int Vector::disordered() const{
int n = 0;
for (int i = 1; i < _size; i++)
n += (_elem[i - 1]>_elem[i]);//逆序则计数
return n;//向量有序当且仅当n=0
}
template
T& Vector::operator[](Rank r) const{//重载下标操作符
return _elem[r]; //0 <= r < _size
}
template
int Vector::remove(Rank lo, Rank hi){//区间删除[lo,hi)
if (lo == hi) return 0;//单独处理退化情况
while (hi < _size) _elem[lo++] = _elem[hi++];//[hi, _size)顺次前移
_size = lo; shrink();//更新规模,若有必要则缩容
return hi - lo;//返回被删除元素的数目
}
template
T Vector::remove(Rank r){//单元素删除,可作为区间删除的特例
T e = _elem[r];//备份删除的元素
remove(r, r + 1);//调用区间删除算法
return e;//返回被删除的元素
}
template
void Vector::shrink(){
if (_capacity < DEFAULT_CAPACITY << 1)return;//不至于收缩到DEFAULT_CAPACITY以下
if (_size << 2>_capacity)return;//已25%为界
T* oldElem = _elem; _elem = new T[_capacity >>= 1];//容量减半
for (int i = 0; i < _size; i++) _elem[i] = oldElem[i];//复制原内容
delete[] oldElem;//释放原空间
}
template
Rank Vector::find(T const & e, Rank lo, Rank hi) const{//无序向量的顺序查找:返回最后一个元素e的位置;失败时,返回lo-1
while ((lo < hi--) && (e != _elem[hi]));//从后顺序查找
return hi;//若hi
int Vector::deduplicate(){//无序向量去重操作
int oldSize = _size;//记录原规模
Rank i = 1;
while (i < _size)
(find(_elem[i], 0, i) < 0) ?
i++ ://若无雷同则继续向后考察
remove(i);//否则删除重复元素
return oldSize - _size;//返回规模变化量 即被删除元素的个数
}
template
int Vector::uniquify(){//有序向量重复去重算法(高效版)
Rank i = 0, j = 0;//各对互异元素的秩
while (++j<_size)
if (_elem[i] != _elem[j])
_elem[++i] = _elem[j];//发现不同时向前移动至前者的紧邻右侧
_size = ++i; shrink();//直接劫除尾部多余元素
return j - i;//向量规模变化量,即被删除元素的个数
}
template
void Vector::sort(Rank lo, Rank hi){//向量区间[lo,hi)排序
switch (rand()%5){//随机选取排序算法。可根据具体问题的特点灵活选取或者扩充
case 1:bubbleSort(lo, hi); break;//起泡排序
case 2:selectionSort(lo, hi); break;//选择排序
case 3:mergeSort(lo, hi); break;//归并排序
case 4:heapSort(lo, hi); break;//堆排序
default:quickSort(lo, hi);//快速排序
}
}
template
Rank Vector::search(T const& e, Rank lo, Rank hi) const{//在有序向量的区间[lo,hi)内,确定不大于e的最后一个节点的秩
return(rand() % 2) ? binSearch(_elem, e, lo, hi) : fibSearch(_elem, e, lo, hi);//各按照50%随机使用二分查找和fibonacci查找
}
template
void Vector::bubbleSort(Rank lo, Rank hi){//向量的起泡排序
while (lo < (hi = bubble(lo, hi)));//逐趟做扫描交换直至全序
}
template
Rank Vector::bubble(Rank lo, Rank hi){//一趟扫描交换
Rank last = lo;//最右侧的逆序对初始化为[lo-1,lo]
while (++lo_elem[lo]){
last = lo;//更新最右侧逆序对位置记录,并
swap(_elem[lo - 1], _elem[lo]);//通过交换使局部有序
}
return last;//返回最右侧的逆序对位置
}
/*
template
void swap(T const& A, T const& B){//交换两个T类型元素
T C = B;
B = A; A = C;
}
*/
template
void Vector::mergeSort(Rank lo, Rank hi){
if (hi - lo < 2) return;//单元素区间自然有序,否则。。。
int mi = (lo + hi) / 2;//以中点为界
mergeSort(lo, mi);//分别排序
mergeSort(mi, hi);
merge(lo, mi, hi);//归并
}
template//有序向量的归并
void Vector::merge(Rank lo, Rank mi, Rank hi){//各自有序子向量[lo,mi) 和[mi,hi)
T* A = _elem + lo;//合并后的向量A[0,hi - lo) = _elem[lo,hi)
int lb = mi - lo; T*B = new T[lb];//前子向量B[0,1b)= _elem[lo,mi)
for (Rank i = 0; i < lb; i++)B[i] = A[i];//复制前子向量
int lc = hi - mi; T* C = _elem + mi;//后子向量C[0,1c) = _elem[mi,hi)
for (Rank i = 0, j = 0, k = 0; (j < lb) || (k < lc);){//B[j] 和 C[k]中的小者续至A末尾
if ((j < lb) && (!(k < lc) || (B[j] <= C[k]))) A[i++] = B[j++];
if ((k < lc) && (!(j < lb) || (C[k] <= B[j]))) A[i++] = C[k++];
}
delete[] B;//释放临时空间B
}//归并后得到完整的有序向量[lo,hi)
//模板方法
//Fibonacci查找算法(版本A)
template
static Rank fibSearch(T* A, T const & e, Rank lo, Rank hi){
Fib fib(hi - lo);//用O(log_phi(n = hi - lo)时间创建Fib数列
while (lo < hi){//每次迭代可能要做两次比较判断,有三个分支
while (hi - lo < fib.get()) fib.prev();//通过向前顺序查找 至多迭代几次?
Rank mi = lo + fib.get() - 1;//确定形如Fib(k) -1 的轴点
if (e < A[mi]) hi = mi;//深入前半段[lo,mi)继续查找
else if (A[mi] < e) lo = mi + 1;//深入后半段(mi,hi)继续查找
else return mi;//在mi处命中
}//成功查找可以提前终止
return -1;//查找失败
}//有多个命中的元素时,不能保证返回秩最大者,失败时简单返回-1,不能确定失败的位置
//
/*
//二分查找算法(版本A):在有序向量的区间[lo, hi)内查找元素e
template
static Rank binSearch(T* A, T const & e, Rank lo, Rank hi){
while (lo < hi){//每次迭代可能要做两次比较判断,有三个分支
Rank mi = (lo + hi) >> 1;//以中点为轴点
if (e < A[mi])hi = mi;//深入前半段[lo,mi)继续查找
else if (A[mi] < e) lo = mi + 1;//深入后半段(mi,hi)继续查找
else return mi;//在mi处命中
}//成功查找提前终止
return -1;//查找失败
}//有多个命中的元素时,不能保证返回秩最大者,失败时简单返回-1,不能确定失败的位置
//二分查找算法(版本B)
template
static Rank binSearch(T*A, T const& e, Rank lo, Rank hi){
while (1 < hi - lo){//每步迭代仅需做一次比较判断,有两个分支;成功查找不能提前终止
Rank mi = (lo + hi) >> 1;//以中点为轴点
(e < A[mi]) ? hi = mi : lo = mi;//经比较后确定深入[lo,mi)或者[mi,hi)
}//出口时hi= lo +1,查找区间仅含有一个元素A[lo]
return(e == A[lo]) ? lo : -1;//查找成功时返回对应的秩,否则返回-1
}//有多个命中的元素时,不能保证返回秩最大者,失败时简单返回-1,不能确定失败的位置
*/
//
//二分查找算法(版本C)
template
static Rank binSearch(T* A, T const& e, Rank lo, Rank hi){
while (lo < hi){//每步迭代仅需做一次比较判断,有两个分支;成功查找不能提前终止
Rank mi = (lo + hi) >> 1;//以中点为轴点
(e < A[mi]) ? hi = mi : lo = mi + 1;//经过比较后确定[lo,mi)或(mi,hi)查找
}
return --lo;//循环结束时,lo为大于e的元素的最小秩,故lo-1为不大于e的元素的最大秩
}//有多个命中元素时,总能保证返回秩最大者;查找失败时,能够返回失败的位置
#endif // !VECTOR_H
#ifndef LISTNODE_H
#define LISTNODE_H
typedef int Rank;//秩
#define ListNodePosi(T) ListNode* //列表节点位置
template struct ListNode{//列表节点模板类(以双向链表形式实现)
//成员
T data; ListNodePosi(T) pred; ListNodePosi(T) succ;
//构造函数
ListNode(){}//针对header 和trailer的构造
ListNode(T e, ListNodePosi(T) p = NULL, ListNodePosi(T) s = NULL) :
data(e), pred(p), succ(s){}//默认构造器
//操作接口
ListNodePosi(T) insertAsPred(T const& e);//紧靠当前节点之前插入新节点
ListNodePosi(T) insertAsSucc(T const& e);//紧靠当前节点之后插入新节点
};
//类函数定义
template //将e紧靠当前节点之前插入于当前节点所属列表(设有哨兵头节点header)
ListNodePosi(T) ListNode::insertAsPred(T const& e){
ListNodePosi(T) x = new ListNode(e, pred, this);//创建新节点
pred->succ = x; pred = x;//设置正向链接
return x;//返回新节点的位置
}
template //将e紧靠当前节点之后插入于当前节点所属列表(设有哨兵头节点trailer)
ListNodePosi(T) ListNode::insertAsSucc(T const& e){
ListNodePosi(T) x = new ListNode(e, this, succ);//创建新节点
succ->pred = x; succ = x;//设置反向链接
return x;//返回新节点的位置
}
#endif // !LISTNODE_H
#ifndef LIST_H
#define LIST_H
#include "listNode.h"
template class List{//列表模板类
private:
int _size; ListNodePosi(T) header; ListNodePosi(T) trailer;//规模、头尾哨兵
protected:
void init();//初始化
int clear();//清楚所有节点至表空
void copyNodes(ListNodePosi(T), int);//复制列表中自p起的n项
void merge(ListNodePosi(T)&, int, List&, ListNodePosi(T), int);//归并
void mergeSort(ListNodePosi(T)&, int);//归并排序
void selectionSort(ListNodePosi(T), int);//选择排序
void insertionSort(ListNodePosi(T), int);//插入排序
public:
//构造函数
List(){ init(); }
List(List const& L);
List(List const& L, Rank r, int n);//复制列表L中自第r项起的n项
List(ListNodePosi(T) p, int n);//复制列表中自P位置起的n个节点
//析构函数
~List();//释放所有节点
//只读访问接口
Rank size()const{ return _size; };//规模
bool empty()const { return _size <= 0 };//判空
ListNodePosi(T) operator[] (Rank r)const;//重载 支持循秩访问
ListNodePosi(T) first()const{ return header->succ; }//首节点位置
ListNodePosi(T) last()const{ return trailer->pred; }//末节点位置
bool valid(ListNodePosi(T) p){//判断p位置对外是否合法
return p && (trailer != p) && (header != p);
}
int disordered() const;//是否已经有序
ListNodePosi(T) find(T const& e) const{//无序列表查找
return find(e, _size, trailer);
}
ListNodePosi(T) find(T const& e, int n, ListNodePosi(T) p)const;//无序区间查找
ListNodePosi(T) search(T const& e) const{//有序列表查找
return search(e, _size, trailer);
}
ListNodePosi(T) search(T const& e, int n, ListNodePosi(T) p)const;//有序区间查找
ListNodePosi(T) selectMax(ListNodePosi(T), int n);//在p及其n-1各后继中选出最大者
ListNodePosi(T) selectMax(){ return selectMax(header->succ, _size); }//整体最大者
//可写访问接口
ListNodePosi(T) insertAsFirst(T const & e);//将e作为首节点插入
ListNodePosi(T) insertAsLast(T const& e);//将e作为末节点插入
ListNodePosi(T) insertA(ListNodePosi(T) p, T const& e);//将e作为p的后继插入(after)
ListNodePosi(T) insertB(ListNodePosi(T) p, T const& e);//将e作为p的前驱插入(before)
T remove(ListNodePosi(T) p);//删除合法位置p处的节点,返回被删除节点
void merge(List& L){ merge(first(), size, L, L.first, L._size); }//全列表归并
void sort(ListNodePosi(T) p, int n);//列表区间排序
void sort(){ sort(first(), _size); }//整体排序
int deduplicate();//无序去重
int uniquify();//有序去重
void reverse();//前后倒置
void traverse(void(*)(T&));//遍历,visit操作 (函数指针)
template void traverse(VST&);//遍历,依次实施visit操作(函数对象)
};//List
//类函数的定义
//初始化
template
void List::init(){
header = new ListNode();
trailer = new ListNode();
header->succ = trailer;
trailer->pred = trailer;
_size = 0;
}
//无序表的查找
template
ListNodePosi(T) List::find(T const& e, int n, ListNodePosi(T) p) const{
while (0 < n--){//对于p的n个最近的真前驱,从右向左
if (e == (p = p->pred)->data) return p;//逐个比对,直至命中或越界
}
return NULL;//p越界意味着失败
}//失败时返回NULL
//作为首节点插入
template
ListNodePosi(T) List::insertAsFirst(T const& e){
_size++; return header->insertAsSucc(e);//e当做首节点插入
}
//作为末节点插入
template
ListNodePosi(T) List::insertAsLast(T const& e){
_size++; return trailer->insertAsPred(e);//e当做末节点插入
}
//作为当前节点的后继插入
template
ListNodePosi(T) List::insertA(ListNodePosi(T) p, T const& e){
_size++; return p->insertAsSucc(e);//e当做p的后继插入
}
//作为当前节点的前驱插入
template
ListNodePosi(T) List::insertB(ListNodePosi(T) p, T const& e){
_size++; return p->insertAsPred(e);//e当做p的前继插入
}
//基本接口
template
void List::copyNodes(ListNodePosi(T) p, int n){
init();//创建头、尾节点并做初始化
while (n--){//将起自p的n项依次作为末节点插入
insertAsLast(p->data); p = p->succ;
}
}
//重载下标操作符,以通过秩直接访问列表节点(虽方便,效率低,需慎用)
template
ListNodePosi(T) List::operator[] (Rank r) const{
ListNodePosi(T) p = first();//从首节点出发
while (0 < r--)p = p->succ;//顺数第r个节点即是
return p;//目标节点,返回其中所存元素
}
//重载构造函数
template
List::List(List const & L){
copyNodes(L.first(), L._size);
}
template
List::List(List const & L, int r, int n){
copyNodes(L[r], n);
}
//删除合法节点p,返回其数值
template
T List::remove(ListNodePosi(T) p){
T e = p->data;//备份待删除节点的数值(假定T类型可直接赋值)
p->pred->succ = p->succ; p->succ->pred = p->pred;//后继、前驱
delete p; _size--;//释放节点,更新规模
return e;//返回备份的数值
}
//析构函数
template
List::~List(){
clear(); delete header; delete trailer;
}
//清空列表
template
int List::clear(){
int oldSize = _size;
while (0 < _size)//反复删除首节点,直至表为空
remove(header->succ);
return oldSize;
}
//剔除无序列表中的重复节点
template
int List::deduplicate(){
if (_size < 2)return 0;//平凡列表自然无重复
int oldSize = _size;//记录原始规模
ListNodePosi(T) p = header; Rank r = 0;//p从首节点开始
while (trailer != (p = p->succ)){//依次直到末节点
ListNodePosi(T) q = find(p->data, r, p);//在p的r个真前驱中查找雷同者
q ? remove(q) : r++;//若的确存在,则删除之,否则秩加一
}//assert:循环过程中的任意时刻p的所有前驱互不相同
return oldSize - _size;//列表规模变化量,即被删除元素的总数
}
//借助函数指针机制遍历
template
void List::traverse(void(*visit)(T&)){
for (ListNodePosi(T) p = header->succ; p != trailer; p = p->succ)
visit(p->data);
}
//操作器 借助函数对象机制遍历
template
template
void List::traverse(VST& visit){
for (ListNodePosi(T) p = header->succ; p != trailer; p = p->succ)
visit(p->data);
}
//有序列表去重
template
int List::uniquify(){
if (_size < 2)return 0;
int oldSize = _size;
ListNodePosi(T) p = first();
ListNodePosi(T) q;
while (trailer != (q = p->succ)){
if (p->data != q->data) p = q;
else remove(q);
}
return oldSize - _size;
}//只需要遍历整个列表一趟,O(n)
//在有序表内p节点的n个真前驱中找到不大于e的最后者
template
ListNodePosi(T) List::search(T const&e, int n, ListNodePosi(T) p)const{
//assert:0<=n<=Rank(p)<_size
do{
p = p->pred; n--;
} while ((-1 < n) && (e < p->data));//逐个比较直到命中或者越界
return p;
}//失败时,返回区间左边界的前驱(可能是header)
//列表的选择排序算法:对起始于位置p的n个元素排序
template
void List::selectionSort(ListNodePosi(T) p, int n){
ListNodePosi(T) head = p->pred; ListNodePosi(T) tail = p;
for (int i = 0; i < n; i++)tail = tail->succ;//待排序区间(head,tail)
while (1 < n){
ListNodePosi(T) max = selectMax(head->succ, n);
insertB(tail, remove(max));
tail = tail->pred;
n--;
}
}
//从起始位置p的n个元素中选出最大者
template
ListNodePosi(T) List::selectMax(ListNodePosi(T) p, int n){
ListNodePosi(T) max = p;
for (ListNodePosi(T) cur = p; 1 < n; n--){
if (!lt((cur = cur->succ)->data, max->data))
max = cur;
}
return max;
}
//a小于b?
template
bool lt(T a, T b){
return a < b;
}
//列表的插入排序算法:对起始于位置p的n个元素排序
template
void List::insertionSort(ListNodePosi(T) p, int n){
for (int r = 0; r < n; r++){
insertA(search(p->data, r, p), p->data);
p = p->succ; remove(p->pred);
}
}
//有序列表的归并:当前列表中自p起的n个元素,与列表L中自q起的m个元素归并
template
void List::merge(ListNodePosi(T) & p, int n, List&L, ListNodePosi(T) q, int m){
ListNodePosi(T) pp = p->pred;//借助前驱,以便返回前。。。
while (0 < m){//在q尚未移出区间之前
if ((0 < n) && (p->data <= q->data)){//若p仍在区间内且v(p)<=v(q),则
if (q == (p = p->succ))//p归入合并的列表,并替换为其直接后继
break;
n--;
}
else{//若p已经超出了右界或者v(q)succ)->pred));//将q转移至p之前
m--;
}
}
p = pp->succ;//确定归并后区间的(新)起点
}
//列表的归并排序算法:对于起始于位置p的n个元素排序
template
void List::mergeSort(ListNodePosi(T) &p, int n){
if (n < 2) return;//若待排序范围已足够小,则直接返回;否则...
int m = n >> 1;//以中点为界
ListNodePosi(T) q = p;
for (int i = 0; i < m; i++)q = q->succ;//均分列表
mergeSort(p, m); mergeSort(q, n - m);//对前、后子列表分别排序
merge(p, m, *this, q, n - m);//归并
}//注意:排序后,p依然指向归并后区间的(新)起点
//判断列表是否有序
template
int List::disordered()const{
int n=0;
for (ListNodePosi(T) p = header->succ; p->succ != trailer; p = p->succ){
if (p->data > p->succ->data)
n++;
}
return n;
}//返回0表示已有序
#endif // !LIST_H