排序-------面试经常遇到的几大排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37407756/article/details/82591762

 1,简单排序

主要思想是:

先规定传入的待排序数组中第一个arr[0]为假设的最大值,然后将其与数组中的其他的元素进行比较,(下面的代码是对数组中的元素进行降序排列),当遇到比当前值大的数值后,就进行交换,并让其为当前最大值,继续比较,直到在他之后的所有元素比较完毕。然后,开始比较第二个元素arr[1],将其作为当前最大值,然后与在他之后的元素进行比较,以此类推。

程序如下:

void simplesort(int array[], int n)
{
	int tem = 0;
	int k_max;
	for (int i = 0; i < n - 1; i++)
	{
		k_max = i;
		for (int j = i + 1; j < n; j++)
		{
			if (array[k_max] < array[j])
			{
				k_max = j;
			}
			if (k_max != i)
			{
				tem = array[i];
				array[i] = array[k_max];
				array[k_max] = tem;
			}
		}
	}

}

结果:第一行为输入:

2.冒泡排序

主要思想:

遍历待排数组中的所有元素,遍历的方式为两两相邻比较,比较的过程在j的for循环中。由于为升序比较,则若当前元素比下一个元素大则进行交换,由于每次到数组的最后时是本次循环得到的最大元素,(要是第一次遍历完后,则得到的最后一个元素为本数组中最大,第二次遍历后,得到的最后的元素为本数组元素的第二大元素),所以,每次最后的之前得到的可不用在参与比较,所以j的范围不是(0,n-1),而是(0,n-i-1)。

程序如下:

void bubblesort(int array[], int n)
{
	int tem = 0;
	for (int i = 0; i < n ; i++)
	{
		for (int j = 0; j < n-i-1; j++)
		{
			if (array[j] > array[j+1])
			{
				tem = array[j];
				array[j] = array[j+1];
				array[j+1] = tem;
			}
		}
	}

}

运行结果:

3.插入排序

主要思想:

每一步都是将要排序的元素插入到已排好的元素中。即:假如前面有5个元素已经按照从小到大的顺序排好了,现在排第六个元素,则把第六个元素与之前的元素一一比较,如果有比较大(或者小)就交换,否则就退出当前元素与之前已排好的元素比较的循环,再比较下一个元素,将其再与之前的元素进行比较。

程序如下:

void insert(int arr[], int n)
{
	int i, j, temp;
	for ( i = 0; i < n; i++)
	{
		for (j = i; j > 0; j--)
		{
			if (arr[j] < arr[j-1])
			{
				temp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = temp;
			}
			else
			{
				break;
			}
		}
	}
}

结果:

4.希尔排序:

主要思想:

      插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,比较和移动元素均需n-1次。

   而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1。希尔排序通过这种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。然后缩小增量,到增量为1时,其实多数情况下只需微调即可,不会涉及过多的数据移动。

 来看下希尔排序的基本步骤,在此我们选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2,(n/2)/2...1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。

以下是借用其他博客的例子:https://www.cnblogs.com/chengxiao/p/6104371.html

代码如下:

#include "stdafx.h"
#include <stdlib.h>

void shellsort(int array[],int n)
{
	//int len = sizeof(array)/sizeof(array[0]);
	for (int step = n/2 ; step >0; step /=2)
	{
		for (int i = step; i < n; i++)
		{
			int j = i;
			int temp = array[j];
			while ((j-step) >= 0 && array[j-step] > temp)
			{
				array[j] = array[j - step];
				j = j - step;
				array[j] = temp;
			}
			
		}
	}

}
void printArray(int arr[], int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return;
}

int main()
{
	int arr[10] = { 2,5,6,4,3,7,9,8,1,0 };
	printArray(arr, 10);
	shellsort(arr,10);
	printArray(arr, 10);

    
	system("pause");
	return 0;
}

5.快速排序:

1.选择轴值,一般是选取第一个元素的关键码。快排的最坏情况就是如果待排序元素是正序或者逆序,就会将除轴值以外的元素分到轴值的一边。 
2.划分 
①、设置划分区间:i=first,j=end 
②、执行右侧扫描,直到r[j]小于轴值,将r[j]与r[i]交换,i++ 
③、执行左侧扫描,直到r[i]大于轴值,将r[i]与r[j]交换,j- - 
④、重复二到三直到i=j,确定看轴值的所在位置,返回该位置

初始键值序列      23  12  35  6  19  50  28
一次划分后       [19  13  6] 23 [35 50 28]
分别进行快速排序  [6  13] 19
                 6  [13]
                    13
                               [28] 35 [50]
                                28  35
                                        50
最终结果           6  13  19  23  28  35  50

3.对待排序序列进行了一次划分后,在分别对左右两个子序列进行快速排序,以此类推。

void quickSort(int arr[], int _left, int _right) 
{
	int left, right;
	int temp;
	left = _left;
	right = _right;

	if (left <= right)
	{
		temp = arr[left];
		while (left != right)
		{
			//进行右侧遍历
			while (left < right && arr[right] >= temp)
			{
				right--;
			}
			arr[left] = arr[right];

			//进行左侧遍历
			while (left < right && arr[left] <= temp)
			{
				left++;
			}
			arr[right] = arr[left];
		}
		arr[left] = temp;//最后两者指的是同一个
		quickSort(arr, _left, left - 1);  //对基准元素左边的元素进行递归排序
		quickSort(arr, right + 1, _right);  //对基准元素右边的进行递归排序

	}
}

猜你喜欢

转载自blog.csdn.net/m0_37407756/article/details/82591762