常用排序算法总结

注:所有排序都是写的由小到大排序的情况

1.插入排序

1)直接插入排序(稳定)



代码:

void DirectInsertSort(int* arr, int len)
{
	if(NULL==arr || len<=1)
		return;
	int keyIndex;//要插入的值下标
	for(keyIndex=1;keyIndex<len;++keyIndex)
	{
		int key=arr[keyIndex]; //要插入的值
		int sortedIndex=keyIndex-1; //前面已经排好序的值的下标,由后往前比较
		while(sortedIndex>=0 && arr[sortedIndex]>key)
		{
			arr[sortedIndex+1]=arr[sortedIndex];
			--sortedIndex;
		}
		arr[sortedIndex+1]=key;  //注意这里的下标 sortedIndex+1
	}
}
 
2)希尔排序 (不稳定) 

希尔排序好的增量序列的共同特征:

http://baike.baidu.com/view/178698.htm?fromtitle=希尔排序算法&fromid=1801475&type=syn

① 最后一个增量必须为1

② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况

代码:

void ShellSort(int* arr, int len)
{
    if(NULL==arr || len<=1)
	return;
    for (int gap = len / 2; gap > 0; gap /= 2)  //增量(gap/2.2时间效率更好)
        for (int keyIndex = gap; keyIndex < len; ++keyIndex) //插入排序即为gap=1的情况
        {
 
             int key = arr[keyIndex];
             int sortedIndex = keyIndex -gap;
             while(sortedIndex >= 0 && arr[sortedIndex] > key)
             {
                arr[sortedIndex+gap] = arr[sortedIndex];
				sortedIndex -=gap;
              }  
             arr[sortedIndex+gap] = key;
         }
}

2.选择排序

1)直接选择排序(不稳定)

第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,第n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列·

  初始状态 [ 8 3 2 1 7 4 6 5 ] 8 <--> 1

第一次 [ 1 3 2 8 7 4 6 5 ] 3 <--> 2

第二次 [ 1 2 3 8 7 4 6 5 ] 3 <--> 3

第三次 [ 1 2 3 8 7 4 6 5 ] 8 <--> 4

第四次 [ 1 2 3 4 7 8 6 5 ] 7 <--> 5

第五次 [ 1 2 3 4 5 8 6 7 ] 8 <--> 6

第六次 [ 1 2 3 4 5 6 8 7 ] 8 <--> 7

第七次 [ 1 2 3 4 5 6 7 8 ] 排序完成

代码:

void DirectChooseSort(int* arr, int len)
{
	if(NULL==arr || len<=1)
		return;
	for(int keyIndex=0;keyIndex<len-1;++keyIndex)
	{
		int minIndex=keyIndex;
		for(int leftIndex=keyIndex+1;leftIndex<len;++leftIndex) //arr[keyIndex]~arr[len-1]最小值
		{
			if(arr[minIndex]>arr[leftIndex])
				minIndex=leftIndex;
		}
		if(minIndex!=keyIndex)
		{
			int temp=arr[minIndex];
			arr[minIndex]=arr[keyIndex];
			arr[keyIndex]=arr[minIndex];
		}
				
	}
}


2)堆排序(不稳定)---最大堆

最大堆性质:树中每个结点的值都大于或者等于任意一个子结点的值



代码:

给出了非递归和递归方法

//递归方法
void MaxHeapify_Recursively(int* arr, int idx, int len)
{
	int leftIdx=2*idx+1;
	int rightIdx=2*idx+2;

	int maxIdx=idx;//idx,leftIdx和rightIdx中最小值的下标
	if(leftIdx<len && arr[maxIdx]<arr[leftIdx])
		maxIdx=leftIdx;
	if(rightIdx<len && arr[maxIdx]<arr[rightIdx])
		maxIdx=rightIdx;
	if(maxIdx!=idx)
	{
		int temp=arr[idx];
		arr[idx]=arr[maxIdx];
		arr[maxIdx]=temp;
		MaxHeapify_Recursively(arr,maxIdx,len);
	}	
}

//非递归循环方法
void MaxHeapify_Iteratively(int* arr, int idx, int len)
{
	while(idx<len/2)
	{
		int leftIdx=2*idx+1;
		int rightIdx=2*idx+2;
		int maxIdx=idx;//idx,leftIdx和rightIdx中最小值的下标
		if(leftIdx<len && arr[maxIdx]<arr[leftIdx])
			maxIdx=leftIdx;
		if(rightIdx<len && arr[maxIdx]<arr[rightIdx])
			maxIdx=rightIdx;
		if(maxIdx!=idx)
		{
			int temp=arr[idx];
			arr[idx]=arr[maxIdx];
			arr[maxIdx]=temp;
			idx=maxIdx;
		}
		else
			return;
	}
}

void BuildMaxHeap(int* arr, int len)
{
	for(int i=len/2-1;i>=0;--i)
		MaxHeapify_Recursively(arr,i,len);
}

void MaxHeapSort(int*arr, int len)
{
	if(NULL==arr || len<=1)
		return;
	BuildMaxHeap(arr,len);
	for(int i=len-1;i>=1;--i)
	{
		int temp=arr[0];
		arr[0]=arr[i];
		arr[i]=temp;
		MaxHeapify_Recursively(arr,0,i);
	}
}

3.交换排序

1)冒泡排序(稳定)

代码:

void BubbleSort(int *arr, int len)
{
	if(NULL==arr || len<=1)
		return;
	bool isOrdered=true;     //判断在一次冒泡过程时没有发生交换,即为已经排序好
	for(int i=1;i<len-1;++i) //冒泡找到第i大的数
		for(int j=0;j<len-i;++j)
		{
			if(arr[j+1]<arr[j])
			{
				int temp=arr[j];
				arr[j]=arr[j+1];
				arr[j+1]=temp;
				isOrdered=false;
			}
			if(isOrdered)
				break;
		}
}


2)快速排序(不稳定)


代码:(使用尾递归的随机化快排)

void Swap(int & a, int &b)  
{  
    int temp=b;  
    b=a;  
    a=temp;  
} 

int Partition(int *arr, int start, int end)  
{  
    int index=rand()%(end-start+1)+ start; //产生[start,end]之间的随机整数
    Swap(arr[index],arr[end]);   
	
    int small=start-1;
    for(index=start;index<end;++index)  
    {  
        if(arr[index]<arr[end])  
        {  
            ++small;
	    if(small<index)
		Swap(arr[small],arr[index]);     
        }  
    }  
    ++small;
    Swap(arr[small],arr[end]); 
    return small;  
}
void TailQuickSort(int *arr,int length, int start, int end)   //尾递归
{  
	if(NULL==arr || length<=1 || start<0 || end>=length)
		return;
	while(start<end)
	{
		int index=Partition(arr,start,end); 
		if((index-start)<(end-index))  
		{
			TailQuickSort(arr,length, start,index-1); 
			start=index+1; 
		}  
		if((index-start)>=(end-index)) 
		{  
			TailQuickSort(arr,length,index+1,end);  
			end=index-1;  
		}  
	}
}



4.归并排序(稳定)


代码:

void Merge(int* arr, int start, int end, int leftEnd)
{
	int *pOrdered=new int[end-start+1];
	int index=0;
	int leftBegin=start;
	int rightBegin=leftEnd+1;

	while(leftBegin<=leftEnd && rightBegin<=end)
	{
		if(arr[leftBegin]<=arr[rightBegin])
			pOrdered[index++]=arr[leftBegin++];
		else
			pOrdered[index++]=arr[rightBegin++];
	}

	while(leftBegin<=leftEnd)
		pOrdered[index++]=arr[leftBegin++];
	while(rightBegin<=end)
		pOrdered[index++]=arr[rightBegin++];

	for(int i=0;i<index;++i)
		arr[start++]=pOrdered[i];
	delete[] pOrdered;
	pOrdered=NULL;
}

void MergeSort(int*arr, int len, int start, int end)
{
	if(NULL==arr || len<=1 || start<0 || end>=len)
		return;
	if(start<end)
	{
		int leftEnd=(end+start)/2;
		MergeSort(arr, len, start, leftEnd);
		MergeSort(arr,len, leftEnd+1, end);
		Merge(arr, start, end, leftEnd);
	}
}

5.线性时间排序

1)计数排序(稳定)

数组中每个数都在[0,k]之间


代码:

void CountSort(int *arr ,int len, int k)
{
	if(NULL==arr || len<=1 || k<0)
		return;
	int* countArr=new int[k+1];
	int* sortedArr=new int[len];

	for(int m=0;m<k+1;++m)
		countArr[m]=0;
	for(int i=0;i<len;++i)
		++countArr[arr[i]];
	for(int j=1;j<k+1;++j)
		countArr[j]+=countArr[j-1];

	for(int l=len-1;l>=0;--l)
	{
		sortedArr[countArr[arr[l]]-1]=arr[l]; //注意这里的下标 countArr[arr[l]]-1
		--countArr[arr[l]];
	}

	for(int i=0;i<len;++i)
		arr[i]=sortedArr[i];
	delete[] countArr;
	countArr=NULL;
	delete[] sortedArr;
	sortedArr=NULL;
}

2)基数排序


代码:

(以十进制为例,设每一位的排序基于计数排序的思想)

int MaxBits(int* arr, int len,int base) //辅助函数,求数据的最大位数
{
    int nMaxBits = 1; 
    for(int i = 0; i<len; ++i)
    {
        while(arr[i] >= base)
        {
            base *= 10;
            ++nMaxBits;
        }
    }
    return nMaxBits;
}
void RadixSort(int* arr, int len) //基数排序
{
	if(NULL==arr || len<=1)
		return;
	int base=10;
	int nMaxBits= MaxBits(arr,len,base);
	int* countArr=new int[base+1];
	int* sortedArr=new int[len];
	int radix=1;
	for(int i=0;i<nMaxBits;++i)    //由低位到高位按照计数排序的思想排序
	{
		for(int m=0;m<base+1;++m)
			countArr[m]=0;
		for(int i=0;i<len;++i)
			++countArr[(arr[i]/radix)%base];
		for(int j=1;j<base+1;++j)
			countArr[j]+=countArr[j-1];

		for(int l=len-1;l>=0;--l)
		{
			int bitNum=(arr[l]/radix)%base;
			sortedArr[countArr[bitNum]-1]=arr[l]; //注意这里的下标 countArr[bitNum]-1
			--countArr[bitNum];
		}

		for(int i=0;i<len;++i)
			arr[i]=sortedArr[i];	
		radix*=10;
	}
	delete[] countArr;
	countArr=NULL;
	delete[] sortedArr;
	sortedArr=NULL;
}

3)桶排序


代码:







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值