程序员面试中的几种典型排序方法

包括:插入排序、选择排序、交换排序、归并排序、希尔排序、堆排序、快速排序


//程序猴2013.6.24
#include "stdafx.h"

//直接插入排序,思想:保证前面0~i-1共i个元素已经排序,将A[i]插入合适的位置
template<typename T> void InsertSort(T A[],int N)
{
	T Tmp;
	int i,j;
	for (i=1;i<N;i++)
	{
		Tmp = A[i];
		for (j=i;j>0;j--)
		{
			if (Tmp<A[j-1])
			{
				A[j]=A[j-1];
			}
			else
				break;
		}
		A[j] = Tmp;
	}
}


template<typename T> void BinaryInsert(T A[],int i)
{
	int Left = 0;
	int Right = i-1;
	while(Left<=Right)
	{
		int Mid = (Left + Right)/2;
		if (A[i]>A[Mid])
			Left = Mid + 1;
		else
			Right = Mid - 1;
	}
	T Tmp = A[i];
	for (int j=i;j>Left;j--)
		A[j] = A[j-1];
	A[Left] = Tmp;
}
//折半插入排序,思想:保证前面0~i-1共i个元素已经排序,将A[i]通过折半查找的方式插入合适的位置
template<typename T> void BinaryInsertSort(T A[],int N)
{
	for (int i=1;i<N;i++)
	{
		BinaryInsert(A,i);
	}
}

//希尔排序(缩小增量排序),思想:先将整个带排序序列分成若干子序列分别进行直接插入排序,
//待整个序列中的记录“基本有序”,即所有子序列均已有序,再对整个记录进行一次插入排序
template<typename T> void ShellSort(T A[],int N)
{
	int Increment,i,j;T Tmp;
	for(Increment=N/2;Increment>=1;Increment/=2)
	{
		for (i = Increment;i<N;i++)
		{
			Tmp = A[i];
			for(j=i;j>=Increment&&A[j-Increment]>Tmp;j-=Increment)
				A[j] = A[j-Increment];
			A[j] = Tmp;
		}
	}
}

//交换排序之冒泡法,思想:保证排在第i位置的是后面i~N中最小(大)的
template<typename T> void BubbleSort(T A[],int N)
{
	int i,j;
	bool exchange = 1;
	T Tmp;
	for (i=1;i<N&&exchange;i++)
	{
		for (j=N-1;j>=i;j--)
		{
			//exchange = 0;
			if (A[j-1]>A[j])
			{
				Tmp = A[j];
				A[j] = A[j-1];
				A[j-1] = Tmp;
				//exchange = 1;
			}
		}
	}
}

template<typename T> void Swap(T& A,T& B)
{
	T Tmp = A;
	A = B;
	B = Tmp;
}

template<typename T> void QSort(T A[],int l,int u)
{
	if (l>=u)
		return;
	T Tmp = A[l];
	int i = l,j = u + 1;
	while(1)
	{
		do 
		{
			i++;
		} while (i<=u&&A[i]<Tmp);
		do
		{
			j--;
		}while  (A[j]>Tmp);
		if (i>j)
			break;
		Swap(A[i],A[j]);
	}
	Swap(A[l],A[j]);
	QSort(A,l,j-1);
	QSort(A,j+1,u);
}
//快速排序,思想:通过一次排序将待排序列分割成两个独立的部分,其中一部分中的元素小于另外一部分的元素(通过中间一个元素来划分)
//分别对这两部分继续进行分割,排序,以达到整个序列有序
template<typename T> void QuickSort(T A[],int N)
{
	QSort(A,0,N-1);
}


//选择排序,思想:每一趟在i~n-1的元素中选择最小的作为第i个记录
template<typename T> void SelectSort(T A[],int N)
{
	T Tmp;
	int i,j,index;
	for (i=0;i<N;i++)
	{
		Tmp = A[i];
		index = i;
		for(j=i+1;j<N;j++)
		{
			if (A[j]<Tmp)
			{
				Tmp = A[j];
				index = j;
			}
		}
		A[index] = A[i];
		A[i] = Tmp;
	}
}

template<typename T> void AdjustHeap(T A[],int i,int N)
{
	int Child;
	T Tmp;
	for (Tmp=A[i];2*i+1<N;i=Child)
	{
		Child = 2*i + 1;
		if (Child<N-1&&A[Child+1]>A[Child])
			Child++;
		if (A[Child]>Tmp)
		{
			A[i] = A[Child];
		}
		else
			break;
		A[Child] = Tmp;
	}

}

//堆排序,思想:首先建立一个大头堆,再将第0元素与最后第N-i-1元素互换,第N-i-1元素即在其最终位置;再调整堆,反复进行直至最后一个元素
template<typename T> void HeapSort(T A[],int N)
{
	int i;
	for (i=N/2-1;i>=0;i--)//完全二叉树中,结点标号大于N/2-1的结点都为叶子节点
	{
		AdjustHeap(A,i,N);
	}
	for(i=N-1;i>=0;i--)
	{
		Swap(A[0],A[i]);
		AdjustHeap(A,0,i);
	}
}

template<typename T> void Merge(T A[],T TmpArray[],int l,int Mid,int u)
{
	int i = l,j = Mid + 1,k = l;
	while(i<=Mid&&j<=u)
	{
		if (A[i]<=A[j])
			TmpArray[k++] = A[i++];
		else
			TmpArray[k++] = A[j++];
	}
	while(i<=Mid)
		TmpArray[k++] = A[i++];
	while(j<=u)
		TmpArray[k++] = A[j++];
	for (i=l;i<=u;i++)
		A[i] = TmpArray[i];
}

template<typename T> void MSort(T A[],T TmpArray[],int l,int u)
{
	if (l<u)
	{
		int Mid = (l + u)/2;
		MSort(A,TmpArray,l,Mid);
		MSort(A,TmpArray,Mid+1,u);
		Merge(A,TmpArray,l,Mid,u);
	}
}

//归并排序,思想:第一步:将原序列分成两个子序列分别进行归并排序,
//               第二步,申请临时空间,使其大小为两个已经排序序列之和,用于存放排序后的序列
//               第三步,合并两个子序列放入临时空间,再从临时空间中取出
template<typename T> void MergeSort(T A[],int N)
{
	T* TmpArray = new T[N];
	if (TmpArray)
	{
		MSort(A,TmpArray,0,N-1);
	}
	else
		printf("Error!\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
	int A[10] = {7,4,5,9,3,8,6,1,2,0};
	printf("排序前\n");
	for (int i = 0;i<10;i++)
	{
		printf("%d ",A[i]);
	}
	printf("\n");
	/*InsertSort(A,10);
	for (int i = 0;i<10;i++)
	{
		printf("%d ",A[i]);
	}*/
	printf("归并排序后\n");
	MergeSort(A,10);
	for (int i = 0;i<10;i++)
	{
		printf("%d ",A[i]);
	}
	return 0;
}

运行结果









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值