C语言常见面试题2 之 常考排序算法

(1) 编程实现直接插入排序(稳定排序算法)

基本思想:
每一趟将一个待排序的记录,按其关键字的大小插入到已经排好序的一组记录的适当位置上,直到所有待排序记录全部插入为止。

#include <iostream>
using namespace std;

void insert_sort(int a[], int n)
{
	int i, j, temp;
	for(i=1; i<n; i++)
	{
		temp = a[i];
		for(j=i-1; j>=0 && temp <a[j]; j-- )
		{
			a[j+1] = a[j];
		}
		a[j+1] = temp;
	}
}

void print_array(int a[], int len)
{
	for(int i=0; i<len; i++)
	{
		cout << a[i] <<" " ;
	}
	cout << endl;
}

int main()
{
	int a[] = {7, 3, 5, 8, 9, 1, 2, 4, 6};
	cout << "befor insert sort";
	print_array(a, 9);
	insert_sort(a, 9);
	cout<< "after insert sort" ;
	print_array(a, 9);

	return 0;
}

(2)编程实现希尔(Shell)排序(属于插入排序算法,不稳定)

基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量
=1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

该方法实质上是一种分组插入方法

实现如下:

初始时取序列的一半为增量,以后增量减半,直至为1.

#include <iostream>
using namespace std;

void shell_port(int a[], int len)
{
	int h, i, j, temp;
	for(h=len/2; h>0; h=h/2)//控制增量
	{
		for(i=h; i<len; i++)//这个for循环就是前面的直接插入排序
		{
			temp = a[i];
			for(j=i-h; j>=0 && a[j]>temp; j-=h)
			{
				a[j+h] = a[j];
			}
			a[j+h] = temp;
		}
	}
}

void print_array(int a[], int len)
{
	for(int i=0; i<len; i++)
	{
		cout << a[i] <<" " ;
	}
	cout << endl;
}

int main()
{
	int a[] = {7, 3, 5, 8, 9, 1, 2, 4, 6};
	cout << "befor shell sort";
	print_array(a, 9);
	shell_port(a, 9);
	cout<< "after shell sort" ;
	print_array(a, 9);

	return 0;
}

(3)编程实现冒泡排序(稳定排序)
这个算法的基本思想就不介绍了。
实现如下:

#include <iostream>
using namespace std;

void bubble_port(int a[], int len)
{
	int exchange, i, j, temp;
	for(i=0; i<len-1; i++)//进行n-1趟扫描
	{
		exchage=0;
		for(j=len-1; j>=i; j--)//从后往前比较,这样最小值冒泡到开头部分
		{
			if(a[j+1] < a[j])
			{
				temp = a[j+1];
				a[j+1] = a[j];
				a[j] = temp;
				exchange = 1;
			}
		}
		if(exchange != 1)
			return;
	}
}

void print_array(int a[], int len)
{
	for(int i=0; i<len; i++)
	{
		cout << a[i] <<" " ;
	}
	cout << endl;
}

int main()
{
	int a[] = {7, 3, 5, 8, 9, 1, 2, 4, 6};
	cout << "befor bubble sort";
	print_array(a, 9);
	bubble_port(a, 9);
	cout<< "after bubble sort" ;
	print_array(a, 9);

	return 0;
}

(4)编程实现快速排序

基本思想:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

#include <iostream>
using namespace std;

void quick_port(int a[], int low, int high)
{
	int i, j, pivot;
	if(low < high )
	{
		pivot = a[low];
		i = low;
		j = high;
		while(i < j)
		{
			while(i<j && a[j] >= pivot)
			{
				j--;
			}
			if(i < j)
				a[i++] = a[j];//将比pivot小的元素移到低端
			
			while(i<j && a[i] <= pivot)
			{
				i++;
			}
			if(i < j)
				a[j--] = a[i];//将比pivot大的元素移到高端		
		}
		a[i] = pivot;/将pivot移到最终位置
		quick_port(a, low, i-1);//对左区间递归排序
		quick_port(a, i+1, high);//对右区间递归排序	
	}
}

void print_array(int a[], int len)
{
	for(int i=0; i<len; i++)
	{
		cout << a[i] <<" " ;
	}
	cout << endl;
}

int main()
{
	int a[9] = {54, 38, 96, 23, 15, 72, 60, 45, 83};
	cout << "befor quick sort";
	print_array(a, 9);
	quick_port(a, 0, 8);
	cout<< "after quick sort" ;
	print_array(a, 9);

	return 0;
}

(5)各种排序算法速度的性能比较
下面哪种排序法对1,2,3,5,4最快?
A. quick sort
B. buble sort
C. merge sort

选择排序算法时,需要考虑以下几点:
数据的规模;
数据的类型;
数据已有的顺序

一般来说,当数据规模较小时,应选择直接插入排序或者冒泡排序。这些排序算法在数据量小时,基本体现不出差别。

考虑数据的类型,比如全部是正整数时,应该考虑使用桶排序。

考虑数据已有顺序,快速排序是一种不稳定的排序(当然可以改进)。对于大部分数据已经有序的情况,快排会浪费大量不必要的步骤。我们说快速排序好,是指大量随机数据下,使用快速排序的效果最理想,而不是指所有情况。

根据题目来看,1,2,3,5,4数据量极小,而且基本有序。此时冒泡排序是最佳选择。

(6)各种排序算法时间复杂度的比较
冒泡排序: O(n^2)
选择排序: O(n^2)
插入排序: O(n^2)
快速排序:不稳定,最理想情况下是O(nlog2n),最坏是O(n^2)
堆排序: O(nlogn)
归并排序: O(nlog2n)

备注:
上述内容是本人学习《C和C++程序员面试秘笈》的读书笔记

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页