算法学习第一幕:排序算法1

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法学习第一幕:排序算法1相关的知识,希望对你有一定的参考价值。

    排序算法应该是大学毕业后用到频率较高的为数不多的几个算法之一,通常情况下根据原理不同分为几个不同的类别,对我个人来说,主要的类别:

    1,随意写随意用无视效率的冒泡,插入,选择三种基本排序

    2,最常用的效率相对前三种较好的快速排序,快排

    3,神特么除了多年写作业刷题库没有遇到过实际应用场景的堆排、归并排序

冒泡排序

首先我们介绍的是冒泡排序,这个应该是接触排序时学会的第一种排序方式,早在久远的初中普及VB时代就用过冒泡排序,其根本原理是每次比较相近的两处,如果二者顺序与要求的排序顺序相反则交换二者顺序,这样每次应该至少一个元素排到它所应该在的位置

 1 void maopao_sort(int a[])
 2 {
 3     int temp = 0;
 4     for(int i = 0; i < n - 1; i++) {
 5         
 6         for (int j = 0; j < n - 1 - i; j++){
 7             if (a[j] < a[j+1]){
 8                 temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
 9             }
10         }
11         for(int i =0 ; i<10;i++)
12             cout<<a[i]<<" ";
13         cout<<endl;
14     }
15 }

运行结果:

技术分享

从结果中我们很明显的看到,如果存在已经排好的序列,程序是依然会继续运行,直到彻底循环完O(n^2)才结束,针对这个,可以通过加入标识位来判断,如果已经排好序的位置,将不会进行处理。

技术分享
 1 void maopao_sort2 ( int a[], int n) {
 2     int temp = 0;
 3     int i = n -1;  //初始时,最后位置保持不变
 4     while ( i > 0) {
 5         int flag = 0; //每趟开始时,无记录交换
 6         for (int j = 0; j < i; j++) {
 7             if (a[j]> a[j+1]) {
 8                 flag = j; //记录交换的位置
 9                 temp = a[j];
10                 a[j]=a[j+1];
11                 a[j+1]=temp;
12             }
13         }
14         i= flag; //为下一趟排序作准备
15         
16         for(int i =0 ; i<10;i++)
17             cout<<a[i]<<" ";
18         cout<<endl;
19     }
20 }
View Code

技术分享少了一次。。。。

 

插入排序

插入排序在我的理解里就像我们小时候打扑克摸牌,从牌堆里抽排,手初始时是空,然后按照从小到大,或者从大到小顺序排列,手中形成有序序列后,新摸得牌就会顺序检索它应该所在的为止,插入,插入位置后面的牌顺序后移一位

 1 void insertSort(int a[], int n)
 2 {
 3     for(int i = 1; i < n; i++) {
 4         if(a[i] < a[i - 1]){
 5             int j = i - 1;
 6             int x = a[i];
 7             a[i] = a[i-1];
 8             while(x < a[j]){
 9                 a[j+1] = a[j];
10                 j--;
11             }
12             a[j+1] = x;
13         }
14     }
15     
16 }

技术分享

效果如图。。。非常非常明显的看到,主要损失的效率在于存在较长的顺序序列时,该方法依然逐个进行。据说改进方法希尔排序属于插入排序升级版,因为并不熟悉,后期研究后加入。

 

选择排序

选择排序,选择最大/最小元素接在已拍好序列后

 1 for(int i = 0; i < n; i++){
 2     int min = a[i]; 
 3     int temp = 0;
 4     int index = i;
 5     for (int j = i + 1;j < n; j++) {
 6         if (a[j] < min) { 
 7             min = a[j]; 
 8             index = j;
 9         }       
10     }       
11         
12     temp = a[i]; 
13     a[i] = min;
14     a[index]= temp;
15 }

技术分享

快速排序

快速排序,使用了分治和递归的方法,将排序的时间复杂度降到了nlgn,虽然不稳定,属于常用的理解很方便的一种排序,主要原理: 任选数组头尾任一元素作为标尺flag,将小于flag的元素放到左边,大于flag的元素放到右边,这样形成了两个小的序列,随后对这两个小序列如上方法进行递归。网上可以直接搜索快速排序gif,很简洁明了的告诉如何实现的。

 1 void quick_sort(int a[], int left, int right)
 2 {
 3     if(left<right)
 4     {
 5         int i = left;
 6         int j = right;
 7         int x = a[i];
 8         
 9         while(i<j)
10         {
11             while(i<j&&a[j]>x)
12                 j--;
13             if(i<j){
14                 a[i] = a[j];
15                 i++;
16             }
17             while(i<j&&a[i]<x)
18                 i++;
19             if(i<j){
20                 a[j] = a[i];
21                 j--;
22             }
23         }
24         a[i] = x;
25         quick_sort(a, left, i-1);
26         quick_sort(a, i+1, right);
27     }
28 }

技术分享

以上是关于算法学习第一幕:排序算法1的主要内容,如果未能解决你的问题,请参考以下文章

算法学习第五篇:排序算法与二分法

排序算法

JavaScript算法(冒泡排序选择排序与插入排序)

几种常见的排序算法分析学习

死磕算法之冒泡排序

排序算法学习(直接插入排序,希尔排序,选择排序,堆排序,冒泡排序)