数据结构(排序算法:基本思想、代码实现)

一、冒泡排序

如果已经全部排序,所需的关键字比较次数[n-1]和记录移动次数[0]均达到最小值,时间复杂度O(n)

如果全部反序,所需的关键字比较次数[n(n-1)/2]和记录移动次数[3*n*(n-1)/2]均达到最大值,时间复杂度O(n^2)

基本思想:

1、第一个数和第二个数比较,如果第一个比第二个大,交换位置,第二个和第三个比较,重复,第一次比较N-1次

2、重复N-i次,每次把最大的数放在最后

 1 public class BubbleSort
 2 {
 3     public void sort(int[] a)
 4     {
 5         int temp = 0;
 6         for (int i = a.length - 1; i > 0; --i)
 7         {
 8             for (int j = 0; j < i; ++j)
 9             {
10                 if (a[j + 1] < a[j])
11                 {
12                     temp = a[j];
13                     a[j] = a[j + 1];
14                     a[j + 1] = temp;
15                 }
16             }
17         }
18     }
19 }

缺点:效率低(需要比较n*(n-1)/2次)

二、选择排序

如果已经全部排序,所需的关键字比较次数[n-1]和记录移动次数[0]均达到最小值,时间复杂度O(n)

如果全部反序,所需的关键字比较次数[n(n-1)/2]和记录移动次数[n]均达到最大值,时间复杂度O(n^2)

基本思想:

1、每一次循环找出最值,不急着交换,放到每一次循环结束再交换

 1 void SelectSort(RecordType r[], int length) /*对记录数组r做简单选择排序,length为待排序记录的个数*/
 2 {
 3     int temp;
 4     for ( i=0 ; i< length-1 ; i++) //n-1趟排序
 5     {
 6         int index=i; //假设index处对应的数组元素是最小的
 7         for (int j=i+1 ; j < length ; j++)  //查找最小记录的位置
 8             if (r[j].key < r[index].key )
 9                 index=j;
10         if ( index!=i)  //若无序区第一个元素不是无序区中最小元素,则进行交换
11         {
12             temp     = r[i];
13             r[i]     = r[index];
14             r[index] = temp;
15         }
16     }
17 }

冒泡排序和选择排序比较:

冒泡排序法是两两依次比较,并做交换,交换的次数多。
选择排序法是每次循环找出最值,循环结束后将最值调整到合适位置,交换的次数少。

时间复杂度相同[O(n^2)],但是换位操作,选择排序是O(n),冒泡排序是O(n^2/2)

三、快速排序(对冒泡排序的改进)

最佳情况下时间复杂度是 O(nlogn)。但是最坏情况下可能达到O(n^2)

基本思想:

1、先从数列中取出一个数作为基准数
2、分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
3、再对左右区间重复第二步,直到各区间只有一个数

 1 public static void quickSort(int[] arr){
 2     qsort(arr, 0, arr.length-1);
 3 }
 4 private static void qsort(int[] arr, int low, int high){
 5     if (low < high){
 6         int pivot=partition(arr, low, high);        //将数组分为两部分
 7         qsort(arr, low, pivot-1);                   //递归排序左子数组
 8         qsort(arr, pivot+1, high);                  //递归排序右子数组
 9     }
10 }
11 private static int partition(int[] arr, int low, int high){
12     int pivot = arr[low];     //枢轴记录
13     while (low<high){
14         while (low<high && arr[high]>=pivot) --high;
15         arr[low]=arr[high];             //交换比枢轴小的记录到左端
16         while (low<high && arr[low]<=pivot) ++low;
17         arr[high] = arr[low];           //交换比枢轴小的记录到右端
18     }
19     //扫描完成,枢轴到位
20     arr[low] = pivot;
21     //返回的是枢轴的位置
22     return low;
23 }

四、插入排序

基本思想:

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入

 1     void insertion_sort(int a[], int n)  
 2     {  
 3         int i,j,tmp;  
 4         for (i = 1; i < n; i++) {  
 5             tmp = a[i];  
 6             for (j = i - 1; j >= 0 && a[j] > tmp; j--) {  
 7                 a[j+1] = a[j];  
 8             }  
 9             a[j+1] = tmp;  
10         }  
11     }  
博客园:http://www.cnblogs.com/zhuziyu/
Copyright ©2018 不是植物
【转载文章务必保留出处和署名,谢谢!】
原文地址:https://www.cnblogs.com/zhuziyu/p/8748126.html