排序算法——冒泡、选择、插入

1、冒泡排序

首先在n个数中,从前到后依次比较相邻的两个数,如果前一个数大于后一个数,则交换位置,这样下来可以将n个数中最大的数移动到最后的位置;然后在前n-1个数中,继续上述操作,将第二大的数移动到倒数第二个位置。这样重复n-1次,就可以得到一个从小到大的序列。冒泡排序可以是稳定的,当设置当两个数大小相同则不交换位置时,可以保持序列的稳定性。

1 void bubble_sort_(vector<int> &q){
2     for(int i = q.size() - 1; i > 0; i--){
3         for(int j = 0; j < i; j++){
4             if(q[j] > q[j+1]){
5                 swap(q[j], q[j+1]);
6             }
7         }
8     }
9 }

冒泡排序可以进行优化,这个优化还是蛮重要的,当在前i个数中都没有产生交换时,说明此时序列已经排好序了,那么可以直接break,如果知道是否产生了交换,我们可以设置一个flag,代码如下:

 1 void bubble_sort_(vector<int> &q){
 2     for(int i = q.size() - 1; i > 0; i--){
 3         bool flag = false;
 4         for(int j = 0; j < i; j++){
 5             if(q[j] > q[j+1]){
 6                 swap(q[j], q[j+1]);
 7                 flag = true;
 8             }
 9         }
10         if(!flag) break;
11     }
12 }

2、选择排序

选择排序的思想是先在n个数中,选出一个最小的数,然后把它放到最前面,接着在剩下的数中,选出第二小的数,把它放到第二个位置,这样重复下去,直到所有的数都排好顺序。

 1 void selection_sort_(vector<int> &q){
 2     for(int i = 0; i < q.size() - 1; i++){
 3         int min = i;
 4         for(int j = i + 1; j < q.size(); j++){
 5             if(q[j] < q[min]){
 6                 min = j;
 7             }
 8         }
 9         swap(q[i], q[min]);
10     }
11 }

3、插入排序

插入排序的过程像打牌,当摸到一张新牌后,要在现有的牌中找到一个合适的位置,将新牌插进去。摸到的第一张牌认为是已排好序的,再摸第二张牌的时候,就要比较与第一张的大小然后插入,重复这个操作,直到所有牌都是有序的。插入排序的时间复杂度最坏为O(n2),当给定的待排序的序列是由大到小给出的时候;最好为O(n),当给定的序列已经是排好序的时候。插入排序是稳定的,当遇到相同数的时候,将新牌插入到相同牌的前面,可以保证其稳定性。

在插入排序中,我们将新牌由后往前进行比较,代码如下:

 1 void insertion_sort(vector<int> &q){
 2     for(int i = 1; i < q.size(); i++){
 3         int t = q[i], j;
 4         for(j = i-1; j >= 0; j--){
 5             if(q[j] > t){
 6                 q[j+1] = q[j];
 7             }
 8             else break;
 9         }
10         q[j+1] = t;
11     }
12 }

需要注意第10行的下标界限是j+1,界定的办法有两种,一个是如果第二个循环完整的执行完毕没有break,此时j为-1,所以第10行下标一定为j+1。另一种办法是假设新牌比所有牌都大,第二个循环根本没执行,那么新牌肯定是放在最后的位置了,也就是j+1的位置。

posted @ 2019-10-25 21:56  wtzhang  阅读(228)  评论(0编辑  收藏  举报