排序算法

关键词:插入冒泡选择、希尔归并快排、堆排序


倒着讲

1.堆排序

1.1有关堆与优先队列,看这里堆与优先队列

1.2堆排序的思想:

    最大堆,每次把根从堆中取出来删去,然后从新建堆,并把取出来的元素放到数组的最后

    那么最大的元素被放到n-1的位置,第二大的元素被放到n-2的位置。。。直到最后,数组就变成的由小到大的顺序

 1.3算法复杂度

     最好最差平均都是O(nlogn)

1.4核心代码

void heapsort(int A[], int n)
{
	int maxval;
	Heap H(A, n, n);
	for (int i = 0; i < n; i++)
		maxval = H.removefirst();
}

2.快速排序

2.1快排的思想:
快排的思想可以由BST得来,在BST中,左子树的值都小于根节点,右子树的值都大于等于根节点,因此检索的时候很快很方便。但问题在于二叉树空间占用太大,而且很容易变得不平衡。

因此,产生了快排的思想:
引入一个轴值pivot,这个值类似于BST中的根节点。把数组中小与pivot的值放到pivot的左边,而大于等于pivot的值放到其右边。在利用该思想,分别对轴值左边的部分和右边的部分排序。直到左边和右边的长度<=1.

具体实现的时候,由于不知道有多少个元素比轴值大,多少个元素比轴值小
因此每次把轴值先交换的最后,然后用两个指针,一个从左往右,一个从右往左,如果遇到左边指针指向的值大于轴值,右边指向的值小与轴值,交换两个元素,直到左右指针相遇,就是轴值应该在的位置,在把轴值换回来。

2.2实现代码(代码经过测试)
int findPivot(int A[], int i, int j)
{
	return (i + j) / 2;
}

int partition(int A[], int l, int r, int p)
{
	do {
		while (A[++l] < p);
		while (l<r&&A[--r]>p);
		swap(A, l, r);
	} while (l < r);

	return l;
}
void qsort(int A[], int i, int j)
{
	if (j<=i)return;
	int index = findPivot(A, i, j);
	swap(A, index, j);
	int k = partition(A, i - 1, j, A[j]);
	swap(A, k, j);

	qsort(A, i, k - 1);
	qsort(A, k + 1, j);
}

3.归并排序

3.1思想;
分治的思想。把原数组分成两个子数组,对子数组排序,然后在把两个数组合并起来。
其实该算法的关键就在合并上:把两个已经有序的数组合并成一个有序的数组

实现思想就是用两个指针分别指向这两个数组的开头,然后比较两指针指向的值,选着合适的放入要合并的新数组中并且将指针后移。

3.2实现代码(经过测试)
void mergeSort(int A[], int temp[], int left, int right)
{
	if (left == right)return;
	int mid = (left + right) / 2;
	mergeSort(A, temp, left, mid);
	mergeSort(A, temp, mid + 1, right);

	for (int i = left; i <= right; i++)
		temp[i] = A[i];

	int i1 = left, i2 = mid + 1;
	for (int curr=left;curr<=right;curr++)
	{
		if (i1 == mid + 1)
			A[curr] = temp[i2++];
		else if (i2 > right)
			A[curr] = temp[i1++];
		else if (temp[i1] < temp[i2])
			A[curr] = temp[i1++];
		else
			A[curr] = temp[i2++];
	}


}



4.希尔排序

4. 1思想:
希尔排序可以看做是对插入排序的优化。因为插入排序对于 基本有序的序列很快,并且比较适用于长度比较小的序列。
由以上两个特点,得出希尔排序的思想:
把大序列分成小序列,对小序列插入排序,使整个大序列尽可能的变得基本有序。

4.2代码(经过测试)
//按从小到大排序
void insort(int A[], int n, int incr)
{
	for (int i = incr; i < n; i += incr)
		for (int j = i; j >= incr && (A[j - incr] > A[j]); j -= incr)
			swap(A, j - incr, j);
}

void shellsort(int A[], int n)
{
	for (int i = n / 2; i>2; i /= 2)
		for (int j = i; j >= 0; j--)
		{
			insort(&A[j], n - j, i);
		}
	insort(A, n, 1);
}


5.插入、冒泡、选择排序

5.1插入排序
思想:把新的元素与前面已经排好序的子序列进行比较,插入到合适的位置
代码:把4.2中,insort函数incr置成1,就是插入排序的代码

5.2冒泡排序
思想:每一次最小的元素就像气泡一样冒到数组的最前面
代码:
void bublesort(int A[], int n)
{
	for (int i = 0; i < n - 1; i++)
		for (int j = i+1; j < n; j++)
			if (A[j] < A[i])
				swap(A, i, j);
}

5.3选择
思想:选择排序是对冒泡排序的一种优化,每次记住最小元素的位置,到最后再进行交换
代码:
void selectSort(int A[], int n)
{
	for (int i = 0; i < n; i++)
	{
		int min = i;
		for (int j = n - 1; j > i; j--)
		{
			if (A[j] < A[min])
				min = j;
		}
		swap(A, i, min);
	}	
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值