排序——高效排序算法

本文介绍了四种高效的排序算法:希尔排序,包括其增量序列选择和改进策略;堆排序,解释了堆的性质和实现过程;快速排序,基于分治策略的排序方法;以及归并排序的实现。通过对这些排序算法的理解,有助于提升算法应用能力。
摘要由CSDN通过智能技术生成

1. 希尔排序


1.1 希尔排序(ShellSort)的名字源于他的发现者Donald Shell,该算法是冲破二次时间屏障的第一批算法之一。希尔排序使用一个序列h1,h2,..,ht,叫做增量排序(increment sequence)。只要h1=1,任何增量序列都是可行的。一个重要性知识,一个h[k]-排序的数据(后面将是h[k-1]-排序)保持它的h[k]-排序性。h[k]排序的一般做法是,对h[k]个独立的子数组执行一次插入排序


1.2 增量序列一般认为h1=1 ;h[i+1]=3h[i] +1比较合适


1.3 希尔排序的核心是利用h个分割位置将数组分为多个子数组。可以根据3个不同的特征改进。

(1)增量序列

(2)除最后一次外,其他各次都采用一种简单的排序算法

(3)仅应用于最后一次(h[1]排序)的简单排序算法


 实现:  

template<class T>
void shellSort(T a[], int n)
{
	int i, j, k, leap;
	int increment[20];
	//Create an appropriate number of increments h
	for (leap = 1, i = 0; leap < n; i++)
	{
		increment[i] = leap;
		leap = 3 * leap + 1;
	}
	//loop on the number of different increments h
	for (i--; i >= 0; i--)
	{
		leap = increment[i];
		//loop on the subarrays h-sorted 
		for (j = leap; j < n; j++)
		{
			//insertion sort for subarray containing every 
			if (a[j - leap]>a[j])
			{
				T temp = a[j];
				for (k = j; a[k - leap]>temp&&k >=leap; k -= leap)
					a[k] = a[k - leap];
				a[k] = temp;
			}
		}
	}

}


2. 堆排序 


2.1 堆是具有以下两个属性的二叉树:

(1)每个节点的值不会小于其子节点的值

(2)全是平衡的,最底层的叶子结点都位于最左边的位置上


实现:

template<class T>
void heapSort(T a[], int n)
{
	for (int i = n / 2 - 1; i >= 0; --i)	//create the heap
		moveDown(a, i, n - 1);
	for (int i = n - 1; i >= 1; --i)
	{
		swap(a[0], a[i]);				//move the largest item to a[i]
		moveDown(a, 0, i - 1);				//restore the heap property
	}

}

template<class T>
void moveDown(T a[], int first, int last)
{
	int i = 2 * first + 1;
	
	while (i < last)
	{
	
		if (i + 1 < last&&			//first has two children(2*first+1 and 2*first+2)
			a[i] < a[i + 1])		//and the second is larger than the first
			i++;
		if (a[i] <= a[first])		//the heap property isn't violated by data[first]
			break;

		swap(a[first], a[i]);		//if necessary
		first = i;			//swap child and parent
		i = 2 * first + 1;		//and move down
	}
	
}



3. 快速排序 


3.1 分治策略(divide-and-conquer)

分:将问题分成一些小的问题然后递归求解

治:将分的各个阶段解得的各个答案修补到一起


实现:

template<class T>
void quickSort(T a[], int l,int r)
{
	if (l < r)
	{
		swap(a[l], a[(l + r) / 2]);
		int i = l, j = r;
		T x = a[i];
		while (i < j)
		{
			while (i < j&&a[j] > x)		// 从右向左找第一个小于x的数 
				j--;
			if (i < j)
				a[i++] = a[j];
			while (i < j&&a[i] < x)		// 从左向右找第一个大于等于x的数  
				i++;
			if (i < j)
				a[j--] = a[i];
		}
		a[i] = x;
		quickSort(a, l, i - 1);			//递归调用
		quickSort(a, i + 1, r);
	}
}



4. 归并排序 


4.1 归并排序的主要过程是将多个已经排好序的子数组合并成一个排好序的数组。然而,这个子数组必须先排好序,具体方法是合并更小的、已排好序的子数组。当子数组的元素少于两个时,将数组一分为二的过程就会停止。这个算法本身也是递归的。


实现:

template<class T>
void Merge(T a[], int first, int mid, int last, T temp[])
{
	int i = first, j = mid + 1;
	int m = mid, n = last;
	int k = 0;
	while (i <= m&&j <= n)
	{
		if (a[i] <= a[j])
			temp[k++] = a[i++];
		else
			temp[k++] = a[j++];
	}
	while (i <= m)
		temp[k++] = a[i++];
	while (j <= n)
		temp[k++] = a[j++];

	for (i = 0; i < k; i++)
		a[first + i] = temp[i];
}
template<class T>
void mSort(T a[], int first, int last, int temp[])
{
	if (first < last)
	{
		int mid = (first + last) / 2;
		mSort(a, first, mid, temp);		//左边有序
		mSort(a, mid + 1, last, temp);	<span style="white-space:pre">	</span>//右边有序
		Merge(a, first, mid, last, temp);	//将两个合并
	}
}
template<class T>
bool mergeSort(T a[], int n)
{
	T *p = new T[n];
	if (p == nullptr)
		return false;
	mSort(a, 0, n - 1, p);
	delete[]p;
	return true;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值