排序,应该可以说在数据结构中占很重要的位置,我们常用的排序算法,可以分为两组:
一种是比较排序,主要有:冒泡排序,选择排序,直接插入排序,归并排序,堆排序,快速排序,希尔排序。
另一种是非比较排序,主要有:计数排序,基数排序,桶排序等。
今天我写的是自己对于冒泡排序,选择排序,直接插入排序,希尔排序四个排序算法的浅见。
排序算法,因为是算法,很多同学会觉得很绕,理不清思路,其实没有很难理解,画图就是一个很容易帮我们理解的方法。
注:今天我举的所有例子都是从小到大排序哒、、、
一.冒泡排序(BubbleSort)
冒泡排序通俗的理解它的基本思想就是两个数比较,较大的往下沉,较小的往上冒。
也就是说比较相邻的两个数据,如果第二个数小,就交换位置。就这样两两比较,一直到比较最前两个数据。最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了。继续重复上述过程,依次将第2.3…n-1个最小数排好位置。
平均时间复杂度是:O(n2)
这是外层一次for循环,内层循环一遍的结果,找到的是最小的一个元素,像这样重复外层for循环就能找到第二小,第三小,直到得到最后的结果!
接下来代码实现一下冒泡排序算法的函数;
void Bubble_Sort(int *arr,int len)//冒泡排序
{
assert(arr != NULL);
int i = 0;//控制外层循环
int j = 0;//控制内层循环
int tmp = 0;//交换时用到的临时量
for(i = 0;i<len;i++)//外层for循环
{
for(j = 0;j < len - i - 1;j++)//内层for循环
{
if(arr[j]>arr[j+1])//从后往前判断两个数的大小,如果前一个数大就进入并交换
{
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
接下来我们来优化一下冒泡排序:
void Bubble_Sort(int *arr,int len)//冒泡排序
{
assert(arr != NULL);
int i = 0;//控制外层循环
int j = 0;//控制内层循环
int tmp = 0;//交换时用到的临时量
bool swap;//这个变量是优化算法定义的一个布尔类型变量
for(i = 0;i<len;i++)//外层for循环
{
for(j = 0;j < len - i - 1;j++)//内层for循环
{
swap = false;
if(arr[j]>arr[j+1])
{
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
swap = true;
}
}
if(!swap)
{
return;
}
}
}
大家可以看到,代码中我定义了一个布尔类型的swap变量,外层循环一进去将swap置为false,进入内层循环进行交换,在交换的最后将swap置为true,这里就是每次进入外层循环会判断一下swap的值,如果它为false,说明并没有进入内层交换,说明已经有序,直接退出,交换的少了,是冒泡的一种优化算法。
二. 选择排序(SelctionSort)
选择排序的基本思想:
在长度为n的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;
。。。
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。
这里我画图模拟了外层一二次循环,你可以自己下去把图画完,我们来分析一下,i控制的是外层循环,这里定义一个index_min,我用m代替的,一开始把i赋值给index_min,之后用index_min和j进行比较,j的初始值是i+1,每次用index_min和j进行比较,如果index_min比j大,就把j赋值给index_min,出来判断一下,如果index_min不等于i,说明index_min和j交换律,就把index_min下标对应的值和j下标对应的值进行交换,j++,这样走到最后得到的是第一个数字最小的一个序列,这是到第二次外层循环,i++,再重复上面步骤,直到最后得到的就是从小到大的有序序列。
c语言代码实现如下:
void Select_Sort(int *arr,int len)//选择排序
{
assert(arr != NULL);
int tmp = 0;
int i = 0;
int minx_index = 0;
for(i = 0;i < len-1;i++)
{
minx_index = i;
for(int j = i+1;j < len;j++)
{
if(arr[j] < arr[minx_index])
{
tmp = arr[j];
arr[j] = arr[minx_index];
arr[minx_index] = tmp;
}
}
}
}
三.直接插入排序(Insertion Sort)
直接插入排序,通俗来说就是两个比较,将第三个开始的值往前面的值里按大小插入。
具体算法描述如下:
1.从第一个元素开始,该元素可以认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后向前扫描
3.如果该元素(已排序)大于新元素,将该元素移到下一位置
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置后
重复步骤2~5
这个图似乎画的有点尴尬,大家凑活看,直接插入排序这里依然是双重for循环,i控制外层for循环,就是循环来比较,j控制里层for循环,控制的是比较完要插入时比要插入数大的数向后移的循环,其实也就是比它本身大的数的个数。
我用c语言代码实现一下:
void Insert_Sort2(int *arr,int len)//直接插入排序2
{
assert(arr != NULL);
int i = 0;//控制外层循环
int tmp = 0;//交换时的一个中间量
int j = 0;//控制内层循环
for(i=1;i//外层循环
{
tmp = arr[i];
for(j = i-1;j>=0;j--)
{
if(arr[j]>tmp)
{
arr[j+1] = arr[j];
}
else
{
break;//这里break之后出来执行的是arr[j+1] = tmp;
}
}
arr[j+1] = tmp;
}
}
大家可以看到我上面标注的是插入排序2,插入排序方法很多,我实现了两个,另外一种会贴在最后完整的源码中。
四.希尔排序(Shell)
希尔排序是插入排序的一种又称“缩小增量排序”,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
对于增量的要求是:一组互素的数,且最后一个必须为1
接下来我用c语言代码实现:
void Shell(int *arr,int len,int gap)//希尔排序
{
assert(arr != NULL);
int i = 0;//控制外层循环
int j = 0;//控制内层循环
int tmp = 0;//交换时的中间量
for(i = gap;i//这里的gap是增量
{
tmp = arr[i];
for(j = i-gap;j>=0;j-=gap)
{
if(arr[j]>tmp)
{
arr[j+gap] = arr[j];
}
else
{
break;
}
}
arr[j+gap] = tmp;
}
}
void Shell_Sort(int *arr,int len)
{
assert(arr != NULL);
int drr[] = {5,3,1};//定义一个数组存放增量
int lend = sizeof(drr)/sizeof(drr[0]);//数组求长度
for(int i=1;i//调用Shell()函数
}
}
那么,接下来我贴出全部源码,供你们参考:
#include
#include
#include
void Insert_Sort1(int *arr, int len) //直接插入排序1
{
assert(arr != NULL);
int i = 0, j = 0;
for (i = 1; i < len; i++)
if (arr[i] < arr[i - 1])
{
int temp = arr[i];
for (j = i - 1; j >= 0 && arr[j] > temp; j--)
arr[j + 1] = arr[j];
arr[j + 1] = temp;
}
}
void Insert_Sort2(int *arr,int len)//直接插入排序2
{
assert(arr != NULL);
int i = 0;
int tmp = 0;
int j = 0;
for(i=1;i<len;i++)
{
tmp = arr[i];
for(j = i-1;j>=0;j--)
{
if(arr[j]>tmp)
{
arr[j+1] = arr[j];
}
else
{
break;
}
}
arr[j+1] = tmp;
}
}
void Shell(int *arr,int len,int gap)//希尔排序
{
assert(arr != NULL);
int i = 0;
int j = 0;
int tmp = 0;
for(i = gap;i<len;i++)
{
tmp = arr[i];
for(j = i-gap;j>=0;j-=gap)
{
if(arr[j]>tmp)
{
arr[j+gap] = arr[j];
}
else
{
break;
}
}
arr[j+gap] = tmp;
}
}
void Shell_Sort(int *arr,int len)
{
int drr[] = {5,3,1};
int lend = sizeof(drr)/sizeof(drr[0]);
for(int i=1;ilen,drr[i]);
}
}
void Select_Sort(int *arr,int len)//选择排序
{
assert(arr != NULL);
int tmp = 0;
int i = 0;
int minx_index = 0;
for(i = 0;i < len-1;i++)
{
minx_index = i;
for(int j = i+1;j < len;j++)
{
if(arr[j] < arr[minx_index])
{
tmp = arr[j];
arr[j] = arr[minx_index];
arr[minx_index] = tmp;
}
}
}
}
void Bubble_Sort(int *arr,int len)//冒泡排序
{
assert(arr != NULL);
int i = 0;
int j = 0;
int tmp = 0;
bool swap ;
for(i = 0;i<len;i++)
{
for(j = 0;j<len-i - 1;j++)
{
swap = false;
if(arr[j]>arr[j+1])
{
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
swap = true;
}
}
if(!swap)
{
return;
}
}
}
void Show(int *arr,int len)
{
for(int i = 0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int ar[5] = {0,54,3,78,0};
int len = sizeof(ar)/sizeof(ar[0]);
Insert_Sort1(ar,len);
Show(ar,len);
Insert_Sort2(ar,len);
Show(ar,len);
Shell_Sort(ar,len);
Show(ar,len);
Bubble_Sort(ar,len);
Show(ar,len);
Select_Sort(ar,len);
Show(ar,len);
return 0;
}