经典排序方法详解

来源:互联网 发布:杭州博远软件 编辑:程序博客网 时间:2024/06/07 00:58

1.

交换排序法

首先我们来看一下最简单但是复杂度高的交换排序法,这种方法每次比较一次都需要进行一次交换,但是是我们刚刚学习排序的一个最基本的排序方法

例如 1 5 3 2 4五个数进行由大到小的降序排序

首先比较1 和 5 ,1小于5 这是一次比较,比较完成之后将1和5 进行一次交换;

排序函数如下

int Dsort(int n,int a[])
{
 int i,j;
 int temp;
 for(i=0;i<n-1;i++)
 {
  for(j=i+1;j<n;j++)
  {
      if(a[i]<a[j])
      {
       temp=a[i];
       a[i]=a[j];
       a[j]=temp;
      }
  }
 }
}

这里注意一下,这个函数和别的函数有点不一样就是没有return 返回值,而且在调用这个函数的时候

是这样子调用 Dsort(n,a),就是数组直接写头名字就可以了不用写作a[];


2.

选择排序法

由于交换排序法的交换次数太多导致效率低下,于是我们更新了更好的排序方法,这种办法每次循环比较之后只需要交换一次

它在比较完大小之后并不需要立即交换只需要用一个中间变量将那个大的数(或者小的数)记录下来

例如 1 5 3 2 4

在比较完1和5的大小之后不需要将1 5进行交换,只需要用一个字符K记住当前最大的数K=2;

当比较完一个循环之后再将最大的k和需要交换的数交换,也就是一个循环只要交换一次,大大提高了排序的效率

代码如下

int selectsort(int n,int a[])
{
 int i,k,j;
 int temp;
 for(i=0;i<n-1;i++)
 {
  k=i;
  for(j=i+1;j<n;j++)
  {
    if(a[k]<a[j])
     k=j;
  }
  if(k!=i)
    {
      temp = a[i];
      a[i] = a[k];
      a[k] = temp;
    }
 }
}

最后那个比较K != i,只进行这一次交换


3.

冒泡排序

冒泡排序和前面两种排序的方法是不同的,虽然也是两两比较,通过判断大小然后两两交换,但是比较的方法和交换都是不一样的

下面我们先来看一下冒泡排序的交换办法

经典排序算法 - 冒泡排序Bubble sort

原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,

这样一趟过去后,最大或最小的数字被交换到了最后一位,

然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子

例子为从小到大排序,

原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 |


第一趟排序(外循环)

第一次两两比较6 > 2交换(内循环)

交换前状态| 6 | 2 | 4 | 1 | 5 | 9 |

交换后状态| 2 | 6 | 4 | 1 | 5 | 9 |

 

第二次两两比较,6 > 4交换

交换前状态| 2 | 6 | 4 | 1 | 5 | 9 |

交换后状态| 2 | 4 | 6 | 1 | 5 | 9 |

 

第三次两两比较,6 > 1交换

交换前状态| 2 | 4 | 6 | 1 | 5 | 9 |

交换后状态| 2 | 4 | 1 | 6 | 5 | 9 |

 

第四次两两比较,6 > 5交换

交换前状态| 2 | 4 | 1 | 6 | 5 | 9 |

交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |

 

第五次两两比较,6 < 9不交换

交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |

交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |

 

第二趟排序(外循环)

第一次两两比较2 < 4不交换

交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |

交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |

 

第二次两两比较,4 > 1交换

交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |

 

第三次两两比较,4 < 5不交换

交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |

 

第四次两两比较,5 < 6不交换

交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |

交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |

 

第三趟排序(外循环)

第一次两两比较2 > 1交换

交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |

交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |

 

第二次两两比较,2 < 4不交换

交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |

 

第三次两两比较,4 < 5不交换

交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |

 

第四趟排序(外循环)无交换

第五趟排序(外循环)无交换


排序完毕,输出最终结果1 2 4 5 6 9

冒泡排序执行外层第一轮循环之后,(外层总共执行n-1次循环),如果是升序排序,则数组中最大的一个数放到了最后面(同理如果是降序排序,最小的那个数被放到了最后,)

然后内层循环第二次的时候就不需要比较倒数两个数的大小,所以内层循环会少i次(即内层循环变为n-i-1次)

而不是(for(j=i;j<n-1;j++))这样是不对的,因为这样子内层循环是从第a[i]开始比较,而不是第一个元素a[0],

冒泡的思想是(假设为从大到小排序):

顺序扫描数组元素,将相邻两个数进行比较,将大数调到前面,小数调到后面。

冒泡排序的特点是:

1.如果有 N 个数,则要进行 N - 1 轮排序;

2.在第 i 轮排序中,要进行 N-i 次两两比较

3.可以从前往后排序,也可从后往前排序

代码如下

int bubblesort(int n,int a[])
{
 int i,j,temp;
 for(i=0;i<n-1;i++)
 {
   for(j=0;j<n-i-1;j++)
   {
     if(a[j]<a[j+1])
     {
      temp = a[j];
      a[j] = a[j+1];
      a[j+1] = temp;
     }
   }
 }
}


现在来说一下三种排序的区别
交换排序和选择排序,是将第一个元素先和第2,第3,......第n个数比较进行交换,然后第二层是第二个数和第3个,第4个.....第n个进行比较交换
选择排序思想是一样的,比较也是一样的,只是减少了交换的次数
而冒泡排序,第一轮是将第一个和第二个进行比较交换,然后将第二个和第三个进行比较交换.....将第n-1个和第n个进行比较交换,
第二轮同样是从第一个和第二个进行比较交换,只是这次不用比较到第n个数,因为第一轮之后,最后那个数一定会是最大(或最小),所以这次比较我们只需要比较到第n-2和第n-1个数。





原创粉丝点击