本博客用于第二次初步学习数据结构,由于有了P1基础,本博客相对于P1将更注重细节与知识框架的建立
文章目录
算法
冒泡排序算法
(1)原理: 双重循环,第一重循环判断是否已经排序,第二层进行相邻元素交换。 O(n^2)
(2)关键: 第一重循环中for(1;2;3)的第二个式子为判断式,返回值为bool类型。可以利用此特点设计算法
void BubbleSort(int A[],int n)
{
for(bool sorted = false ; sorted = ! sorted; n--)
{
//sorted若上一步进行了交换此时返回true,反之返回false退出循环
for(int i=1;i<n;i++)
{
if(A[i-1]>A[i])
{
swap(A[i-1],A[i]);
sorted = false;
}
}
}
}
数组倒置递归迭代算法
(1)原理: 数组元素开头变成结尾,由于数组可以下标访问,故可以使用下标进行递归或者迭代交换。首尾逐步交换,直到首>尾就停止交换
(2)算法
递归算法: 逐层递减,常项是当前下标位置交换。递归项是剩余数组元素交换。
//递归算法
void ArrayReverse(int A[],int lo,int hi)
{
if(lo > hi) return
swap(A[lo],A[hi]);
ArrayReverse(A,lo+1,hi-1);
}
//迭代算法
void ArrayReverse(int A[],int lo,int hi)
{
while(lo <= hi)
swap(A[lo++],A[hi--]);
}
数组二分法求和算法
(1)原理: 数组可以直接迭代求和,但是需要进行n次运算。可以利用分而治之的方法,将数组求和分为两个子问题求和,再逐项拆分递归进行
(2)算法解析
int BinarySum(int A[],int lo,int hi)
{
if(lo == hi) return A[lo];
int mid = (hi+lo)>>1;
return BinarySum(A,lo,mid)+BinarySum(A,mid+1,hi);
}
数据结构
Vector
ADT接口
#ifndef VECTOR_H_INCLUDED
#define VECTOR_H_INCLUDED
#include <iostream>
using namespace std;
typedef int Rank;
#define DEFAUT_CAPACITY
template<class Type>
class Vector
{
protected:
Rank _size; //规模
int _capacity; //容量
Type *_elem; //数据区
//***********************************************
void copyFrom(Type const& A,int lo,int hi);
void expand();
void shrink();
public:
//默认构造函数
Vector(int c = DEFAULT_CAPACITY, int s=0, Type v=0)
{
_elem = new Type[_capacity=c];
for(_size=0;_size<s;_size++)
_elem[_size]= v;
};
//复制构造函数
Vector(Type const* A,Rank lo,Rank hi)
{ copyFrom(A,lo,hi); }; //[lo,hi)
Vector(Type const* A,Rank n)
{ copyFrom(A,0,n); }; //整体复制
Vector(Vector<Type> const& V,Rank lo,Rank hi)
{ copyFrom(V._elem,lo,hi); };
Vector(Vector<Type> const& V,Rank n)
{ copyFrom(V._elem,0,V._size); };
//析构函数
~Vector() { delete [] _elem; };
//***********************************************
void unsort(Rank lo,Rank hi);
Rank Find(Type const& e) const
{ return Find(e,0,_size); };
Rank Find(Type const&e,Rank lo,Rank hi);
Rank Insert(Type const& e)
{ return Insert(_size,e); };
Rank Insert(Rank r,Type const& e);
};
/*
函数实现在后续部分
*/
#endif // VECTOR_H_INCLUDED
向量复制器函数与=重载
copyFrom() and operator =
template<class Type>
void Vector<Type>::copyFrom(Type const* A,Rank lo,Rank hi)
{
_elem = new Type[_capacity = 2*(hi-lo)];
_size =0;
while(lo<hi)
{
_elem[_size++] =A[lo++];
}
}
template<class Type>
Vector<Type>& Vector<Type>::operator= (Vector<Type> const& V)
{
if(_elem) delete [] _elem;
copyFrom(V._elem,V.size());
return *this;
}
动态空间管理-扩容&缩容
expand() and shrink()
(1)算法思路: 动态向量的扩容和缩容都遵循创建–>转移–>释放三个步骤,将已有向量数据转移到新的向量空间中
template<class Type>
void Vector<Type>::expand()
{
if(_size <_capacity) return;
if(_capacity <DEFAULT_CAPACITY) _capacity = DEFAULT_CAPACITY;
Type* oldelem =_elem;
_elem = new Type[_capacity<<=1]; //容量翻倍
for(int i=0;i<_size;i++)
_elem[i] =oldelem[i];
delete [] oldelem;
}
template<class Type>
void Vecto<Type>::shrink()
{
if(_capacity <DEFAULT_CAPACITY<<1) return;
if(_size<<2 >_capacity) return; //%25为阈值
Type* oldelem =_elem;
_elem = new Type[_capacity>>=1]; //减半
for(int i=0;i<_size;i++)
_elem[i] =oldelem[i];
delete [] oldelem;
}
置乱器&向量[]直接引用重载
前后两种置乱器函数,第一种在置换过程中使用了向量的直接引用[]重载,而第二种接口函数直接使用了数组的引用进行互换
//向量直接引用重载
template<class Type>
Type& Vector<Type>::operator[] (Rank r) const
{
return _elem[r];
}
//置乱器函数
template<class Type>
void permute(Vector<Type>& V)
{
for(int i=V.size();i>0;i--)
swap(V[i-1],V[rand()%i]); //末位开始向前随机交换
}
//置乱器接口函数
template<class Type>
void Vector<Type>::unsort(Rank lo,Rank hi)
{
Type* V =_elem +lo; //[lo,hi)
for(int i=hi-lo;i>0;i--)
swap(V[i-1],V[rand()%i]);
}
判断器和比较器重载
比对和比较可以通过构建判断比较器或者对判断符号进行重载实现
//小于
template<class Type>
static bool lt(Type* a,Type* b)
{
return lt(*a,*b);
}
template<class Type>
static bool lt(Type& a,Type& b)
{
return a<b;
}
//等于
template<class Type>
static bool eq(Type* a,Type* b)
{
return eq(*a,*b);
}
template<class Type>
static bool eq(Type& a,Type& b)
{
return a==b;
}
无序查找
从末尾向前,注意比对查找。 若找到指定元素返回元素的秩,或者返回-1
(1)算法思路: 循环的判断条件为截至条件前与查找到指定元素。 注意i–;指的是执行完此语句而不是此行语句。所以while(lo<hi-- && _elem[i]!e)中第一次比较的元素是_elem[hi-1[而不是_elem[hi]
template<class Type>
Rank Vector<Type>::Find(Type const& e,Rank a,Rank b)
{
while((lo <hi--)&&(_elem[i] !=e));
return hi; //rank or -1
}
插入&删除
将指定元素插入到指定位置
(1)算法思路:插入步骤: 空间判断–>数据转移–>插入。 其中数据转移可能会消耗大量的时间
template<class Type>
Rank Vector<Type>::Insert(Rank r,Type const& e)
{
expand();
for(int i=_size;i>r;i--)
_elem[i] =_elem[i-1];
_elem[r] =e;
_size++;
return r;
}