void swap(int* a,int* b)
{
int tmp=*a;
*a=*b;
*b=tmp;
}
1、冒泡采用依次比较相邻两个元素大小的方法进行排序,代码如下:
/从小到大排序/
bool SortByBubble(int* pFirst,int* pEnd)
{
//1、参数合法性检查
if(pFirst == NULL || pEnd ==NULL || pEnd-pFirst<=0)
return false;
bool bChange=false;
//2、挪动pEnd到最后一个元素的下一位置
pEnd=pEnd+1;
do{
//3、初始指针位置为第2个元素
int* p=pFirst+1;
bChange=false;
//4、比较相邻元素 只要后面的元素比前面的小 ,就交换位置,直到最后一个元素
while(p<pEnd)
{
if(*(p)<*(p-1))
{
swap(p-1,p);
bChange=true;
}
++p;
}
//5、循环完之后 ,最后一个元素为最大,所以把最后一个位置往前挪一下(此步骤可稍微提高一点效率)
--pEnd;
}while(bChange);
return true;
}
2、插入法
先排前两个,第三个数在已排好的前两个中找到适当位置插入,这样就排好了前三个,第四个在已排好的前三个中找到位置插入。。。依次下去,直到最后一个数。
bool SortByInsert(int* pFirst,int* pEnd)
{
//1、参数合法性检查
if(pFirst == NULL || pEnd ==NULL || pEnd-pFirst<=0)
return false;
//2、获取个数
int n=pEnd-pFirst+1;
//3、从第1个元素开始,每次从右向左看,暂存最右边的这个数,只要在它左边的数比它大,则挪动一个位置
for(int i=1;i<n;++i)
{
int j=i;
int nTmp=pFirst[i];
for(;j>0 && pFirst[j-1]>nTmp; --j)
pFirst[j]=pFirst[j-1];
//4、此处j的最小值为0
pFirst[j]=nTmp;
}
return true;
}
3、选择法
一种选择:假定位置0此刻为最小的数 ,然后从位置1开始每次只要找到比位置0小的数就是该数交换位置,直到最后一个元素,此时位置0为真正最小的数,下一次假定位置1为最小的数,从位置2开始只要找到比位置1小的数就是该数交换位置,直到最后一个元素。。。依次类推
另一种选择:假定位置0此刻为最小的数,然后从位置1开始每次只要找到比位置0小的数就暂存该数,直到最后一个元素,最后,暂存的这个数与位置0这个数做比较,如果比它小,则交换位置,下一次假定位置1为最小的数,从位置2开始只要找到比位置1小的数就是暂存该数,直到最后一个元素,最后,暂存的这个数与位置1这个数做比较,如果比它小,则交换位置。。。依次类推
第一种代码:
bool SortByLikeChose(int* pFirst,int* pEnd)
{
//1、参数合法性检查
if(pFirst == NULL || pEnd ==NULL || pEnd-pFirst<=0)
return false;
//2、获取个数
int n=pEnd-pFirst+1;
for(int i=0;i<n;++i)
{
//3\从i+1到最后一个元素 找最小的放在i处
for(int j=i+1;j<n;++j)
{
if(pFirst[j]<pFirst[i])
swap(&pFirst[i],&pFirst[j]);
}
}
return true;
}
第二种代码:
bool SortByChose(int* pFirst,int* pEnd)
{
//1、参数合法性检查
if(pFirst == NULL || pEnd ==NULL || pEnd-pFirst<=0)
return false;
int* pCurPos=pFirst;
while(pCurPos!=pEnd)
{
//2、暂存当前的最小值及最小值所在位置
int nTmpMin=*pCurPos;
int* pMin=pCurPos;
//3、从当前位置的后一个位置开始搜索
int* pTmp=pCurPos+1;
while(pTmp<=pEnd)
{
if(*pTmp<nTmpMin)
{
nTmpMin=*pTmp;
pMin=pTmp;
}
++pTmp;
}
//4、如果最小值的位置与当前位置不是同一位置,则表明最小值发生改变,交换两个数 。
if(pCurPos!=pMin)
swap(pMin,pCurPos);
//5、挪动当前位置到下一处
++pCurPos;
}
return true;
}
4、快速法
选择中间位置的数作为分界点,,分别从左和从右搜索,,左边只有比分界值小的数则保留,如果遇到大于等于分界值的数则停止并等待,右边只有比分界值大于或等于的数则保留,如果遇到比分界值小的数则等待,此时交换左右两边的数,在交换之前需满足 左边指示的位置必须小于右边的指示位置。 将左半部分递归之前的方法 ,右边也递归之前的方法,代码如下:
bool SortByQuick(int* pFirst,int* pEnd)
{
//1、参数合法性检查(包含终止条件 ,如果只剩一个元素 则不继续)
if(pFirst == NULL || pEnd ==NULL || pEnd-pFirst<=0)
return false;
//2、获取个数
int n=pEnd-pFirst+1;
//3、终止条件:如果只剩两个,则直接比较大小
if(n ==2)
{
if(*pFirst>*pEnd)
swap(pFirst,pEnd);
}else
{
//4、获取最左边、最后边、还有中间位置指针
int* pMid=pFirst+n/2;
int* pLeft=pFirst;
int* pRight=pEnd;
while(pLeft<pRight)
{
//5、找到不小于分界数的位置 ,此处pLeft最多会到pMid处
while(*pLeft<*pMid && pLeft<pMid)
++pLeft;
//6、找到小于分界数的位置 ,此处pRight最多会到pMid处
while(*pRight>=*pMid && pRight>pMid)
--pRight;
//7、因为后面递归会把分界值放在右侧,所以如果此处pLeft已经到了pMid处则不需要交换
if(pLeft<pMid )
swap(pLeft,pRight);
//8、此处pLeft可能到达pMid+1处,pRight可能到达pMid-1处
++pLeft;
--pRight;
}
//9、左侧递归(不包含分界值)
SortByQuick(pFirst,pMid-1);
//10、右侧递归(包含分界值)
SortByQuick(pMid,pEnd);
}
return true;
}
5、归并法
归并可理解为先两两排序,然后四个一组排序,然后八个、、依次类推,代码如下:
bool SortByMerge(int* pFirst,int* pEnd)
{
//1、参数合法性检查(包含终止条件 ,如果只剩一个元素 则不继续)
if(pFirst == NULL || pEnd ==NULL || pEnd-pFirst<=0)
return false;
//2、获取个数
const int n=pEnd-pFirst+1;
//3、终止条件:如果只剩两个,则直接比较大小
if(n ==2)
{
if(*pFirst>*pEnd)
swap(pFirst,pEnd);
}else
{
//4、获取分界点 分为两份
int* pMid=pFirst+n/2;
//5、先排左侧
SortByMerge(pFirst,pMid);
//6、再排右侧
SortByMerge(pMid+1,pEnd);
//7、此时 左侧是一串从小到大的有序数据 ,右侧同样
int* pTmpLeft=pFirst;
int* pTmpRight=pMid+1;
//8、在堆上分配空间
int* nTmp= new int[n];
int* pStart=nTmp;
//9、移动数据到分配的空间
while(pTmpLeft<=pMid && pTmpRight <=pEnd)
{
//10、如果左边的小,就先放左边到分配的空间
if(*pTmpLeft<*pTmpRight)
{
*nTmp++=*pTmpLeft;
++pTmpLeft;
}
//11、如果右边的小,就放右边到分配的空间
else if(*pTmpLeft>*pTmpRight)
{
*nTmp++=*pTmpRight;
++pTmpRight;
}else
{
//12、如果相等,则左右都放
*nTmp++=*pTmpLeft;
++pTmpLeft;
*nTmp++=*pTmpRight;
++pTmpRight;
}
}
//13、最后总有一个先满足终止条件,所以以下两个while只会执行其中一个 ,
while(pTmpLeft<=pMid)
{
*nTmp++=*pTmpLeft++;
}
while(pTmpRight<=pEnd)
{
*nTmp++=*pTmpRight++;
}
//14、拷贝数据
for(int i=0;i<n;++i)
*pFirst++=pStart[i];
//15、
delete[] nTmp;
}
return true;
}