什么是排序?
排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序,若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程。(源于百度百科)
在计算机领域内,排序的方法有很多种:冒泡排序、快速排序、希尔排序等等。
我们今天了解一下几种简单的排序:
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;
}
运行结果: