快速排序实现细节的思考

    每次隔个一年或半年,回过来重新写快速排序代码,都不知如何入手。在此记录,以便翻阅。

    网友MoreWindows对快速排序的总结非常好,挖坑填数+分治法。每一趟的快速排序QuickSortPart实际上就是一个挖坑填数的过程,然后整个快速排序QuickSort就是使用分治策略分成2块,每块又是对子序列的快速排序。

    关于快速排序时间复杂度,有种简单的计算方法:每次分成两段,那么分的次数就是log2n(即以2为底n的对数,2^x=n,两边对2求对数,x=log2n),每一次处理需要n次计算(两小段包括在内为n),那么时间复杂度就是O(nlog2n)。


// MyTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

void SwapData(int &data1, int &data2);
void BubbleSort(int* iArray,int iNum);
void InsertionSort(int* iArray,int iNum);
void SelectionSort(int* iArray,int iNum);
void QuickSort(int* iArray,int iLeft,int iRight);
int QuickSortPart(int* iArray,int iLeft,int iRight);
void QuickSort(int* iArray,int iNum);
int QuickSortPart(int* iArray,int iNum);

void SwapData(int &data1, int &data2)
{
	int iTemp=0;
	iTemp=data1;
	data1=data2;
	data2=iTemp;
}

void BubbleSort(int* iArray,int iNum)
{
	for (int i=0; i<iNum-1; i++)
	{
		for (int j=0; j<iNum-i-1; j++)//不是for(int j=i; j<iNum-1; j++)
		{
			if (iArray[j]>iArray[j+1])
			{
				//iTemp=iArray[j+1];
				//iArray[j+1]=iArray[j];
				//iArray[j]=iTemp;
				SwapData(iArray[j], iArray[j+1]);
			}
		}
	}
}

/****************************************************************************
插入排序:每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,
直到全部插入完毕。
****************************************************************************/
void InsertionSort(int* iArray,int iNum)
{
	for (int i=1; i<iNum-1; i++)
	{
		for (int j=i; j>0; j--)
		{
			if (iArray[j-1]>iArray[j])
			{
				//iTemp=iArray[j];
				//iArray[j]=iArray[j-1];
				//iArray[j-1]=iTemp;
				SwapData(iArray[j-1], iArray[j]);
			}
		}
	}
}

/****************************************************************************
选择排序:比如在一个长度为N的无序数组中,在第一趟遍历N个数据,找出其中最小的
数值与第一个元素交换,第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个
元素交换......第N-1趟遍历剩下的2个数据,找出其中最小的数值与第N-1个元素交换,
至此选择排序完成。
****************************************************************************/
void SelectionSort(int* iArray,int iNum)
{
	for (int i=0; i<iNum; i++)//0-7
	{
		int iMinIndex=i;//iMinIndex表示最小数据在数组中的索引
		for (int j=i; j<iNum; j++)//0-7
		{
			if (iArray[j]<iArray[iMinIndex])
			{
				iMinIndex=j;
			}
		}
		if (iArray[i]>iArray[iMinIndex])
		{
			SwapData(iArray[i], iArray[iMinIndex]);
		}
		cout << "iMin==" << iArray[i] << endl;//0
	}
}

/****************************************************************************
快速排序:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据
都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,
整个排序过程可以递归进行,以此达到整个数据变成有序序列。
参数:int iLeft代表左索引【数组第一个元素索引】,int iRight代表右索引【数组最
后一个元素索引】
****************************************************************************/
void QuickSort(int* iArray,int iLeft,int iRight)
{
	if (iLeft>=iRight)//漏了此语句,编译器将提示:“如递归所有控件路径,函数将导致运行时堆栈溢出”
	{
		return;
	}
	int iBaseNum=QuickSortPart(iArray,iLeft,iRight);
	QuickSort(iArray,iLeft,iBaseNum-1);//相当于子数组
	QuickSort(iArray,iBaseNum+1,iRight);//相当于子数组
}

/****************************************************************************
每一趟快速排序:首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,
然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为
一趟快速排序。
参数:int iLeft代表左索引【数组第一个元素索引】,int iRight代表右索引【数组最
后一个元素索引】
返回值:返回基准值的最终索引
****************************************************************************/
int QuickSortPart(int* iArray,int iLeft,int iRight)
{
	int iBaseNum=iLeft;
	int i=iLeft;
	int j=iRight;
	while (i<iRight&&j>iLeft&&i<=j)
	{
		while (j>iLeft&&i<=j)
		{
			if (iArray[j]<iArray[iBaseNum])//从右找比基准小的
			{
				SwapData(iArray[j],iArray[iBaseNum]);
				iBaseNum=j;
				j--;
				break;
			}
			else
			{
				j--;
			}
		}
		while (i<iRight&&i<=j)
		{
			if (iArray[i]>iArray[iBaseNum])//从左找比基准大的
			{
				SwapData(iArray[i],iArray[iBaseNum]);
				iBaseNum=i;
				i++;
				break;
			}
			else
			{
				i++;
			}
		}
	}
	return iBaseNum;
}

//2个参数版,参数要额外计算,麻烦
void QuickSort(int* iArray,int iNum)
{
	int iLeft =0;
	int iRight =iNum-1;
	if (iLeft>=iRight)//漏了此语句,编译器将提示:“如递归所有控件路径,函数将导致运行时堆栈溢出”
	{
		return;
	}
	int iBaseNum=QuickSortPart(iArray,iNum);
	int iNum1=iBaseNum-iLeft;
	int iNum2=iNum-iBaseNum-1;
	QuickSort(iArray,iNum1);
	QuickSort(iArray+iBaseNum+1,iNum2);
}

//2个参数版
int QuickSortPart(int* iArray,int iNum)
{
	int iBaseNum=0;
	int i=0;
	int j=iNum-1;
	while (i<iNum-1&&j>0&&i<=j)
	{
		while (j>0&&i<=j)
		{
			if (iArray[j]<iArray[iBaseNum])//从右找比基准小的
			{
				SwapData(iArray[j],iArray[iBaseNum]);
				iBaseNum=j;
				j--;
				break;
			}
			else
			{
				j--;
			}
		}
		while (i<iNum-1&&i<=j)
		{
			if (iArray[i]>iArray[iBaseNum])//从左找比基准大的
			{
				SwapData(iArray[i],iArray[iBaseNum]);
				iBaseNum=i;
				i++;
				break;
			}
			else
			{
				i++;
			}
		}
	}
	return iBaseNum;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//int iArray[8]={1,3,5,7,2,4,6,8};
	int iArray[8]={1,5,2,7,4,3,6,8};
	//BubbleSort(iArray,8);
	InsertionSort(iArray,8);
	//SelectionSort(iArray,8);
	for (int i=0; i<8; i++)
	{
		cout << iArray[i] << " ";//0
	}
	cout << endl;//0

	int iArray2[10]={72,6,57,88,60,42,83,73,48,85};
	//QuickSort(iArray2,0,9);
	QuickSort(iArray2,10);
	for (int i=0; i<10; i++)
	{
		cout << iArray2[i] << " ";//0
	}
	cout << endl;//0
	return 0;
}


参考资料:http://blog.csdn.net/morewindows/article/details/6684558

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值