数据结构:排序(一)

什么是排序?

排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序外部排序,若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程。(源于百度百科)

在计算机领域内,排序的方法有很多种:冒泡排序、快速排序、希尔排序等等。

我们今天了解一下几种简单的排序:

1.冒泡排序:

冒泡排序的原理如下:

1.比较相邻的两个元素,如果第一个比第二个大,就交换它们

2.对每一对相邻元素做同样的工作,从开始的第一对,到最后的一对。做完这个步骤,应该能获取到最大的数字

3.针对除最后一个元素的其他所有元素,重复以上的不步骤

4.持续对越来越少的元素重复以上步骤,直到没有需要交换的元素。

冒泡排序:

void Bubble_sort(int array[],int64_t size)
{
	if(size <= 1){
		return;
	}

	int64_t bound = 0;
	//采用每次循环找到一个最小的数字的方式完成冒泡
	//[0,bound) 就是当前有序区间
	//[bound,size) 就是待排序区间
	for(;bound < size;++bound){
		// 每循环一次,有序区间就增加一个元素
		// 本次循环的目的就是找到一个当前的最小数字
		int64_t cur = size - 1;
		for(;cur > bound; --cur){
			if(array[cur] < array[cur - 1]){
				Swap(&array[cur],&array[cur - 1]);
			}// end if
		}// end for
	}// end for
	return;
}

冒泡排序是一种简单的排序方式,约定按照元素的大小升序排序(也可以降序排序)

时间复杂度:O(N^2)

空间复杂度:O(1)

是一种稳定排序

但由于时间复杂度较高,所以在工作中很少用到冒泡排序。

完整代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void Swap(int *a,int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
	return;
}

void Print(int array[],int64_t size)
{
	int i = 0;
	for(;i < size;++i){
		printf("%d ",array[i]);
	}
	printf("\n");
}

void Bubble_sort(int array[],int64_t size)
{
	if(size <= 1){
		return;
	}

	int64_t bound = 0;
	//采用每次循环找到一个最小的数字的方式完成冒泡
	//[0,bound) 就是当前有序区间
	//[bound,size) 就是待排序区间
	for(;bound < size;++bound){
		// 每循环一次,有序区间就增加一个元素
		// 本次循环的目的就是找到一个当前的最小数字
		int64_t cur = size - 1;
		for(;cur > bound; --cur){
			if(array[cur] < array[cur - 1]){
				Swap(&array[cur],&array[cur - 1]);
			}// end if
		}// end for
	}// end for
	return;
}

int main( void )
{
	int array[]={9,5,2,7};
	int64_t size = sizeof(array)/sizeof(array[0]);
	Bubble_sort(array,size);
	Print(array,size);
	return 0;
}

运行结果:

选择排序:

选择排序的基本思想:

对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较如果后面的元素比他要小则用变量k记住它在数组中的位置,等到循环结束的时候,我们应该找到了那个最小的那个数的下标,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟它交换一下值,这样就找到整个数组中最小的数。然后找到数组中第二小的数,让它跟数组中第二个元素交换一下值,以此类推。

选择排序代码:

void Select_sort(int array[],int64_t size)
{
	if(size <= 1){
		return;
	}

	int64_t bound = 0;
	//[0,bound) 有序空间
	for(;bound < size;++bound){
	     //找出当前区间中最小的元素
	     //使用 array[bound] 来作为擂台
		int64_t cur = bound;
		for(;cur < size;++cur){
			if(array[cur] < array[bound]){
				Swap(&array[cur],&array[bound]);
			}// end if
		}// end for
	}// end for
	return;
}

选择排序的各项指标:

时间复杂度:O(N^2)

空间复杂度:O(1)

是一种不稳定排序

和冒泡排序一样,选择排序也由于时间复杂度较高,工作中很少用到。

完整代码入下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void Swap(int *a,int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
	return;
}

void Print(int array[],int64_t size)
{
	int i = 0;
	for(;i < size;i++){
		printf("%d ",array[i]);
	}
	printf("\n");
}


void Select_sort(int array[],int64_t size)
{
	if(size <= 1){
		return;
	}

	int64_t bound = 0;
	//[0,bound) 有序空间
	for(;bound < size;++bound){
	     //找出当前区间中最小的元素
	     //使用 array[bound] 来作为擂台
		int64_t cur = bound;
		for(;cur < size;++cur){
			if(array[cur] < array[bound]){
				Swap(&array[cur],&array[bound]);
			}// end if
		}// end for
	}// end for
	return;
}

int main( void )
{
	int array[]={9,5,2,7};
	int64_t size = sizeof(array)/sizeof(array[0]);
	Select_sort(array,size);
	Print(array,size);
	return 0;
}

运行结果:

插入排序:

插入排序有很多种,我们先介绍最普通的一种:直接插入排序,后面会介绍一种希尔排序,其实它就是一种特殊的插入排序

插入排序的基本思想:

(1) 设置监视哨r[0],将待插入记录的值赋值给r[0];

(2) 设置开始查找的位置j;

(3) 在数组中进行搜索,搜索中将第j个记录后移,直至r[0].key≥r[j].key为止;

(4) 将r[0]插入r[j+1]的位置上。

插入排序的代码如下:

void Insert_sort(int array[],int64_t size)
{
	if(size <= 1){
		return;
	}
	
	int64_t bound = 1;
	//[0,bound) 有序区间
	//[bound,size) 待排序区间
	//把 bound 位置的元素尝试插入到前面有序线性表的合理位置
	for(;bound < size;++bound){
		int bound_value = array[bound];
		int64_t i = bound;
		for(;i > 0;--i){
			if(array[i - 1] > bound_value){
				array[i] = array[i - 1];
			}
			else{
				break;
			}
		}
		//下面这行代码表示两重含义:
		//1.当前数组中这个元素已经小于bound_value,就需要:
		// 把bound_value 放到这个元素的后面
		// 也就是放到下标为i的位置上
		//2.处理循环结束的情况,如果 bound_value 
		//刚好是当前有序顺序表中最小的元素
		// 此时达到 i == 0 的时候,循环就退出了
		// 此时需要把 bound_value 设置到下标为0的位置上
		array[i] = bound_value;
	}
}

插入排序的各项指标:

时间复杂度:O(N^2)

空间复杂度:O(1)

插入排序是一种稳定排序

完整代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void Print(int array[],int64_t size)
{
	int n = 0;
	for(;n < size;i++){
		printf("%d ",array[n]);
	}
	printf("\n");
}

void Insert_sort(int array[],int64_t size)
{
	if(size <= 1){
		return;
	}
	
	int64_t bound = 1;
	//[0,bound) 有序区间
	//[bound,size) 待排序区间
	//把 bound 位置的元素尝试插入到前面有序线性表的合理位置
	for(;bound < size;++bound){
		int bound_value = array[bound];
		int64_t i = bound;
		for(;i > 0;--i){
			if(array[i - 1] > bound_value){
				array[i] = array[i - 1];
			}
			else{
				break;
			}
		}
		//下面这行代码表示两重含义:
		//1.当前数组中这个元素已经小于bound_value,就需要:
		// 把bound_value 放到这个元素的后面
		// 也就是放到下标为i的位置上
		//2.处理循环结束的情况,如果 bound_value 
		//刚好是当前有序顺序表中最小的元素
		// 此时达到 i == 0 的时候,循环就退出了
		// 此时需要把 bound_value 设置到下标为0的位置上
		array[i] = bound_value;
	}
}

int main( void )
{
	int array[]={9,5,2,7,3,8,4,18};
	int64_t size = sizeof(array)/sizeof(array[0]);
	Insert_sort(array,size);
	Print(array,size);
	return 0;
}

运行结果:

猜你喜欢

转载自blog.csdn.net/LSFAN0213/article/details/81258371