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

八大排序方法总结 


<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>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值