您的位置:首页 > 其它

排序方法总结(递归与非递归)

2016-03-20 19:43 260 查看
八大排序方法总结

<span style="font-size:18px;">#pragma once
#ifndef _SORT_HEADER_
#define _SORT_HEADER_
#include<vector>
using std::vector; //切记不要忘记
template<class T>
void Swap(T& a, T& b)
{
T temp;
temp = a;
a = b;
b = temp;
}

#define SAFE_DELETE(p)	\
{						\
if ((p) != NULL)	\
{					\
delete (p);		\
(p) = NULL;		\
}					\
}
#define ISEXIST(p)      \
{						\
if (nullptr == (p)) \
{return; }			\
}

typedef void(*Functype)(int* p, int len); //定义一个和排序函数相同类型的函数指针

void GetRandomVal(int* p, int len);
void SortSelect(Functype pFunc, int* p, int len);//参数为一个函数指针类型

void PrintArray( const int* p, int len);
void BulSort( int* p, int len);
void InsertSort( int* p, int len);
void SelectSort(int* p, int len);

void InsertByStep(int* p, int len, int d);
void ShellSort(int* p, int len, int* step, int count);

int AdjustMiddle(int* p, int lest, int right);
int Partation( int* p, int left, int right);
void QuickSort( int* p, int left, int right);
void UnCurQuickSort(int* p, int left, int right);

void AdjustHeap(int *p, int len,int root);
void HeapSort(int *p, int len);

void MergeArray(int* p, int begin, int mid, int end);
void MergeSort(int *p,int begin,int end);
void UnCurMergeSort(int *p, int len);

//一下为基数排序需要使用到的函数
void RadixSort(int *p,int len);
void CollectBucket(int *p,vector<vector<int>>& Vec);
int GetMaxCount(int *p,int len);
int GetPosVal(int num, int nPos);

#endif</span>
<span style="font-size:18px;">
</span>
<span style="font-size:18px;">
</span>
<span style="font-size:18px;">//以下为实现文件 </span>
<span style="font-size:18px;">#include"Sort.h"
#include<ctime>
#include<stdlib.h>
#include<assert.h>
#include<stack>
#include<string>
#include<iostream>
using namespace std;

void SortSelect(Functype pFunc, int* p, int len)//参数为一个函数指针类型
{
pFunc(p,len);
}
void GetRandomVal(int* p, int len)
{
if (nullptr == p || len < 1)
{
return;
}
srand((unsigned int)time(0));
for (int i = 0; i < len; ++i)
{
p[i] = rand();
}
}

void PrintArray(const int* p, int len)
{
ISEXIST(p);
if (len < 1)
{
return;
}
for (int i = 0; i < len; ++i)
{
cout << p[i]<<" ";
}
cout << endl;
}

//标准插入  可以改为没有 临时变量 有待思考
void InsertSort(int* p, int len)
{
ISEXIST(p);
if (len < 1)
{
return;
}
int temp = p[0], j = 0;
for (int i = 1; i < len; ++i)
{
temp = p[i];
for (j = i - 1; j >= 0 && p[j] > temp; --j)
{
p[j + 1] = p[j];
}
p[j + 1] = temp;
}
}

//标准冒泡
void BulSort(int* p, int len)
{
if (nullptr == p || len < 1)
{
return;
}
bool IsExchange = false;
for (int i = 0; i < len; ++i)
{
IsExchange = false;
for (int j = 0; j <len-i-1; --j)
{
if (p[j] > p[j + 1])
{
Swap(p[j],p[j+1]);
}
IsExchange = true;
}
//PrintArray(p,len);
if (!IsExchange)
{
break;//当前一趟 并未发生交换
}
}
}

//标准选择排序
void SelectSort(int* p, int len)
{
if (nullptr == p || len < 1)
{
return;
}
int minIndex = 0;
for (int i = 0; i < len-1; ++i)//只进行 len-1 趟 最后一个 为最大值
{
minIndex = i;
for (int j = i+1; j < len; ++j)//从i+1 开始 找比前边小的
{
if (p[j] < p[minIndex])
{
minIndex = j;
}
}
if (i != minIndex)
{
Swap(p[i], p[minIndex]);
}
}
}

void InsertByStep(int* p, int len, int d)
{
if (nullptr == p || len < 1 || d >= len || d < 1)
{
return;
}
int temp=0,j=0;
for (int i = d; i < len; ++i)
{
temp = p[i];
for (j = i - d; j >= 0 && p[j] > temp; j-=d)
{
p[j + d] = p[j];
}
p[j + d] = temp;
}
}

void ShellSort(int* p, int len, int* step, int count)
{
if (nullptr == p || nullptr == step || len < 0 || count < 0)
{
return;
}
for (int i = 0; i < count; ++i)
{
InsertByStep(p, len, step[i]);
}
}

int Partation(int* p, int left, int right)
{
if (nullptr == p || left < 0 || right <= 0||left>right)
{
return -1;
}
AdjustMiddle(p,left,right);
int i = left;
int j = right;
int key = p[left];
while (i < j)
{
while (i < j&&p[j] >= key)//寻找第一个  比key小的值
{
--j;
}
p[i] = p[j];
while (i < j&&p[i] <= key)//寻找第一个 比key大的值
{
++i;
}
p[j] = p[i];
}
//循环退出时  i==j 并且 被覆盖的值 应该在 i位置上
p[i] = key;
return i;
}

int Partation1(int* p, int left, int right)//划分函数很重要
{
int i = 0;
int index = left;
int temp = p[left];
int mid=AdjustMiddle(p, left, right);
Swap(p[left],p[mid]);//将中间元素 作为轴值
Swap(p[index], p[right]);// index 与 right 调换
for (i = left; i<right; i++)
{
if (p[i]<temp)
{
Swap(p[index], p[i]);//遇到比基准值小就调换
index++;//基准位后移
}
}
Swap(p[index], p[right]);// index 与 right 调换
return index;
}

void QuickSort(int* p,int left,int right)
{
if (nullptr == p || left < 0 || right <= 0 || left >= right)
{
return;
}
int nIndex;
if (left < right)
{
nIndex= Partation(p, left, right);
QuickSort(p,left,nIndex-1);
QuickSort(p,nIndex+1,right);
}
}

void AdjustHeap(int *p, int len, int root)
{
if (nullptr == p || len < 0 || root < 0 || root >= len||2*root+1>=len)
{
return;
}
int temp = p[root];//保存更节点的值
int i = 2 * root + 1;//左孩子
while (i < len)
{
if (i + 1 < len&&p[i] < p[i + 1])
{
++i;//寻找两个孩子中 值较大的节点
}
if (p[i] > temp)
{
p[(i - 1) / 2] = p[i];//将较大的节点 赋值给父节点
}
else
{
break;//否则 已经是大根堆 退出
}
i = 2 * i + 1;//向下移动
}
p[(i - 1) / 2] = temp;//找到对应位置 放入
}

//标准 堆排序 注意堆调整数组如果0位置空缺  则在排序时 会带来麻烦
void HeapSort(int* p, int len)
{
if (nullptr == p || len <= 1)
{
return;
}
int root = len/2-1;//可通过规律获得
for (int i = len/2; i>0; --i)//将无序堆 调整为有序堆 调整次数为 len/2
{
AdjustHeap(p,len,root--);
}
for (int i = 0; i < len; ++i)
{
Swap(p[0],p[len-i-1]);//每次和最后一个元素交换
AdjustHeap(p,len-i-1,0);//每次堆调整 长度减1
}
}

void MergeArray(int* p, int begin, int mid, int end)
{
ISEXIST(p);
if (begin < 0 || mid < 0 || end < 0 || begin > mid || mid > end)
{
return;
}
int i = begin, j = mid + 1;//mid位于 前半个数组 并且 end为下标
int k = 0;
int* pTemp = new int[end-begin+1];
if (nullptr == pTemp)
{
throw "can not apply memory!";;
}
while (i <= mid&&j <= end)
{
if (p[i] < p[j])
{
pTemp[k++] = p[i++];
}
else
{
pTemp[k++] = p[j++];
}
}
while (i <= mid)
{
pTemp[k++] = p[i++];
}
while (j <= end)
{
pTemp[k++] = p[j++];
}
i = 0;
while (i < k)
{
p[i+begin]=pTemp[i];
++i;
}
delete[] pTemp;
pTemp = nullptr;
}

void MergeSort(int *p, int begin, int end)
{
if (nullptr == p || begin < 0 || end<0)//等于号 很重要
{
return;
}
if (begin < end)
{
int mid = (end + begin) / 2;
MergeSort(p, begin, mid);
MergeSort(p, mid + 1, end);
MergeArray(p, begin, mid, end);
}
}

void UnCurQuickSort(int* p,int left,int right)
{
assert(nullptr!=p);
assert(left>=0&&right>=left);
stack<int> SPos;
int mid = Partation(p, left, right);
if (left < mid - 1)
{
SPos.push(left);
SPos.push(mid - 1);
}
if (mid + 1 < right)
{
SPos.push(mid + 1);
SPos.push(right);
}
while (!SPos.empty())
{
int high = SPos.top();
SPos.pop();
int low = SPos.top();
SPos.pop();
mid = Partation(p,low,high);
if (low < mid - 1)
{
SPos.push(low);
SPos.push(mid-1);
}
if (mid + 1 < high)
{
SPos.push(mid+1);
SPos.push(high);
}
}
}

void UnCurMergeSort(int *p, int len)
{
assert(nullptr != p);
assert(len>0);
int start = 0;
int step=1;
while (step < len)
{
start = 0;
while (start < len)
{
if (start + 2 * step -1 < len)
{
//需要注意mid是处于前半个区间的  并且都是闭区间
MergeArray(p,start,start+step-1,start+step*2-1);
}
//这个地方可能会出现两种情况
//1:最后只剩下一个step归并单元 这种情况不用再归并
//2:最后剩下一个step归并单元 和一个小于step归并单元
else if(start+step<len&&start+2*step>len)
{
//这个地方处理最后剩下一个半区间
MergeArray(p, start, start + step-1, len-1);
}
start += (step<<1);
}
step <<= 1;
}
}

int AdjustMiddle(int* p, int left, int right)
{
//此函数调整快排过程中轴值得选择 避免恶化
assert(nullptr != 0);
assert(left >= 0 && right >= 0 && left <= right);
if (left == right)
{
return left;
}
int mid = (left + right) << 1;
if (p[left] > p[mid])
{
Swap<int>(p[left],p[mid]);
}
if (p[left] > p[right])
{
Swap<int>(p[left], p[right]);
}
if (p[mid] > p[right])
{
Swap<int>(p[mid], p[right]);
}
return mid;
}

//以下是基数排序使用的函数
void CollectBucket(int *p, vector<vector<int>>& Vec)
{
if (nullptr == p || Vec.empty())
{
return;
}
int k = 0;
for (size_t i = 0; i < Vec.size(); ++i)//表示从 0-9
{
for (size_t j = 0; j < Vec[i].size(); ++j)//表示bucket中的元素个数
{
p[k++] = Vec[i][j];
}
Vec[i].clear();
}
}

void RadixSort(int *p, int len)
{
if (nullptr == p || len < 1)
{
return;
}
//vector <vector<int>> Vec(ncol, vector<int>(nrow,0)); ncol*nrow 二维数组
vector <vector<int>> Vec(10, vector<int>());
int count = GetMaxCount(p, len);
for (int i = 0; i < count; ++i)
{
for (int j = 0; j < len; ++j)
{
Vec[GetPosVal(p[j], i)].push_back(p[j]);
}
CollectBucket(p, Vec);
}
}

int GetMaxCount(int *p, int len)
{
if (nullptr == p || len < 1)
{
return -1;
}
//通过最大值 比较易懂
int count = 1, temp = 10;
for (int i = 0; i < len; ++i)
{
while (abs(p[i]) >= temp)//注意可能有负数
{
temp *= 10;
++count;
}
}
return count;
}
int GetPosVal(int num, int nPos)
{
if (nPos < 0)
{
throw("parameter illegal!");
}
int temp = _Pow_int(10, nPos);
return (num / temp) % 10;
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: