现在的位置: 首页 > 综合 > 正文

基本排序算法复习

2017年11月15日 ⁄ 综合 ⁄ 共 3074字 ⁄ 字号 评论关闭

排序算法

1、冒泡排序

双层循环,内层循环一圈得出一个最小(最大)值。循环和交换复杂度均为n*n。
for(int i=0;i<len;i++)
{
    for(int j=i+1;j<len;j++)
    {
       int temp;
       if(src[i]>src[j])
       {
           temp=src[j];
           src[j]=src[i];
           src[i]=temp;
       }            
    }
}     

2、选择排序

选择排序比较时每次只会记录下最小的(或者最大的)的位置,一轮比较完成之后才会进行对应位置和最小位置(或者最大位置)的交换操作。循环和交换复杂度分别为n*n,n。
 for(int i=0;i<len;i++)
 {
     temp=src[i];
     int j;
     int samllestLocation=i;//最小数的下标
     for(j=i+1;j<len;j++)
     {
        if(src[j]<temp)
        {
            temp=src[j];//取出最小值
            samllestLocation=j;//取出最小值所在下标
        }
     }
     src[samllestLocation]=src[i];
     src[i]=temp;
 }
 
3、插入排序
每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。分为直接插入(如下代码)和折半插入,后者需要折半查找。
void doInsertSort1(int[] src)
{
   int len=src.length;
   for(int i=1;i<len;i++)
   {  
       int temp=src[i];
       int j=i;
      
       while(src[j-1]>temp)
       {
          src[j]=src[j-1];
          j--;
          if(j<=0)
              break;
       }
       src[j]=temp;
   }
}

4、希尔排序

将需要排序的序列划分成为若干个较小的子序列,对子序列进行插入排序,通过则插入排序能够使得原来序列成为基本有序。
这样通过对较小的序列进行插入排序,然后对基本有序的数列进行插入排序,能够提高插入排序算法的效率。

public void sort(int[] data) {

     for(int i=data.length/2;i>2;i/=2){
         for(int j=0;j<i;j++){
             insertSort(data,j,i);
         }
     }
     insertSort(data,0,1);
 }

 private void insertSort(int[] data, int start, int inc) {

     int temp;

     for(int i=start+inc;i<data.length;i+=inc){
         for(int j=i;(j>=inc)&&(data[j]<data[j-inc]);j-=inc){
             SortUtil.swap(data,j,j-inc);
         }
     }
 }

5、快速排序
挖坑填数+分治法:

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

void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
        int i = l, j = r, x = s[l];
        while (i < j)
        {
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
                            j--; 
            if(i < j)
                            s[i++] = s[j];
                    
            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
                            i++; 
            if(i < j)
                            s[j--] = s[i];
        }
        s[i] = x;
        quick_sort(s, l, i - 1); // 递归调用
        quick_sort(s, i + 1, r);
    }
}

6、归并排序

先递归的分解数列,再合并数列就完成了归并排序。
时间复杂度 n*lgn

//将有二个有序数列a[first...mid]和a[mid...last]合并。
void mergearray(int a[], int first, int mid, int last, int temp[])
{
int i = first, j = mid + 1;
int m = mid,   n = last;
int k = 0;

while (i <= m && j <= n)
{
if (a[i] <= a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}

while (i <= m)
temp[k++] = a[i++];

while (j <= n)
temp[k++] = a[j++];
//写入数组
for (i = 0; i < k; i++)
a[first + i] = temp[i];
}
void mergesort(int a[], int first, int last, int temp[])
{
if (first < last)
{
int mid = (first + last) / 2;
mergesort(a, first, mid, temp);    //左边有序
mergesort(a, mid + 1, last, temp); //右边有序
mergearray(a, first, mid, last, temp); //再将两边有序数列合并
}
}
//调用方法
bool MergeSort(int a[], int n)
{
int *p = new int[n];
if (p == NULL)
return false;
mergesort(a, 0, n - 1, p);
delete[] p;
return true;
}

7、堆排序

堆排序
堆建好之后堆中第0个数据是堆中最小的数据。取出这个数据再执行下堆的删除操作。
这样堆中第0个数据又是堆中最小的数据,重复上述步骤直至堆中只有一个数据时就直接取出这个数据。

由于堆也是用数组模拟的,故堆化数组后,第一次将A[0]与A[n - 1]交换,再对A[0…n-2]重新恢复堆。
第二次将A[0]与A[n – 2]交换,再对A[0…n - 3]重新恢复堆,重复这样的操作直到A[0]与A[1]交换。
由于每次都是将最小的数据并入到后面的有序区间,故操作完成后整个数组就有序了

void MinheapsortTodescendarray(int a[], int n)
{
for (int i = n - 1; i >= 1; i--)
{
Swap(a[i], a[0]);
MinHeapFixdown(a, 0, i);
}
}

//  从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
void MinHeapFixdown(int a[], int i, int n)
{
    int j, temp;

temp = a[i];
j = 2 * i + 1;
while (j < n)
{
if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
j++;

if (a[j] >= temp)
break;

a[i] = a[j];     //把较小的子结点往上移动,替换它的父结点
i = j;
j = 2 * i + 1;
}
a[i] = temp;
}

用数组实现最小堆,按元素赋值顺序依次放入a[len-1],a[len-2]...
所以排序完成后是降序数组。

抱歉!评论已关闭.