基本排序算法

对于排序算法来说,需要对代码实现烂熟于胸,知道空间消耗、平均时间复杂度和最差时间复杂度。

稳定的只有:直接插入、冒泡、归并、基数排序。
1.插入;算法适用于少量数据的排序, 时间复杂度 为O(n^2)。是 稳定 的排序方法.
private   static   int [] insertSort( int []arr){
if (arr == null  || arr. length  < 2){
     return  arr;
}
for ( int  i=1;i<arr. length ;i++){
for ( int  j=i;j>0;j--){
if (arr[j]<arr[j-1]){
// TODO :
int  temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
} else {
//接下来是无用功
break ;
}
}
}
return  arr;
}
2.希尔: 缩小 增量 排序
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
public   static   void  shellsort( int [] a){
int  d = a. length ;
  while ( true ){
             for ( int  i=0;i<d;i++){
                 for ( int  j=i;j+d<a. length ;j+=d){
                 int  temp;
                 if (a[j]>a[j+d]){
                    temp=a[j];
                    a[j]=a[j+d];
                    a[j+d]=temp;
                    }
                }
            }
             if (d==1){ break ;}
            d--;
    }
}
3.选择:
public   static   void   selectSort ( int []a)
{
     int  minIndex=0;
     int  temp=0;
     if ((a== null )||(a. length ==0))
         return ;
     for ( int  i=0;i<a. length -1;i++)
    {
        minIndex=i; //无序区的最小数据数组下标
         for ( int  j=i+1;j<a. length ;j++)
        {
             //在无序区中找到最小数据并保存其数组下标
             if (a[j]<a[minIndex])
            {
                minIndex=j;
            }
        }
         if (minIndex!=i)
        {
             //如果不是无序区的最小值位置不是默认的第一个数据,则交换之。
            temp=a[i];
            a[i]=a[minIndex];
            a[minIndex]=temp;
        }
    }
}
4.堆排序:堆排序是一种选择排序。是不稳定的排序方法。时间复杂度为O(nlog2n)。
堆是一种重要的 数据结构,为一棵 完全二叉树, 底层如果用数组存储数据的话,假设某个元素为序号为i( Java数组从0开始,i为0到n-1), 如果它有左子树,那么左子树的位置是2 i+1,如果有右子树,右子树的位置是2 i+2,如果有父节点,父节点的位置是(n-1)/2取整
其基本思想是
1、将要排序的数组创建为一个大根堆。大根堆的堆顶元素就是这个堆中最大的元素。
2、将大根堆的堆顶元素和无序区最后一个元素交换,并将无序区最后一个位置例入有序区,然后将新的无序区调整为大根堆。
3、重复操作,无序区在递减,有序区在递增。
初始时,整个数组为无序区,第一次交换后无序区减一,有序区增一。
每一次交换,都是大根堆的堆顶元素插入有序区,所以有序区保持是有序的。

P.S.
大根堆和小根堆
堆:是一颗完全二叉树。
大根堆:所有节点的子节点比其自身小的堆
小根堆:所有节点的子节点比其自身大的堆
public static void heapS(int[] arr){
if(arr == null || arr.length == 0)
return;
int len = arr.length;
for(int i = (len - 1) / 2; i >= 0; i--){
buildMaxHeap(arr,i,len);
}
for(int i = len - 1; i > 0; i--){
int tmp = arr[0];
arr[0] = arr[i];
arr[i] = tmp;
buildMaxHeap(arr,0,i);
}
}
public static void buildMaxHeap(int[] arr, int start, int len){
int key = arr[start];
for(int i=2*start+1; i<len-1; i=2*i+1){ //i为初始化为节点k的左孩子,沿节点较大的子节点向下调整
if(i<len && arr[i]<arr[i+1]){ //取节点较大的子节点的下标
i++; //如果节点的右孩子>左孩子,则取右孩子节点的下标
}
if(key >= arr[i]){ //根节点 >=左右子女中关键字较大者,调整结束
break;
}else{ //根节点 <左右子女中关键字较大者
arr[start] = arr[i]; //将左右子结点中较大值array[i]调整到双亲节点上
start = i; //【关键】修改k值,以便继续向下调整
}
}
arr[start] = key; //被调整的结点的值放人最终位置
}


5.快排:时间空间复杂度都是O(nlogn),不稳定。
适用于: 被排序的数据完全无序
public   static   void  quicksort( int [] arr, int  low, int  high){
         if (low < high){
             int  mid = getMiddle (arr,low,high);
             quicksort (arr,low,mid-1);
             quicksort (arr,mid+1,high);
        }
    }
     public   static   int  getMiddle( int [] arr, int  low, int  high){
         int  key = arr[low];
         while (low < high){
             while (low < high && arr[high] >= key)
                high--;
            arr[low] = arr[high];
             while (low < high && arr[low] <= key)
                low++;
            arr[high] = arr[low];
        }
        arr[low] = key;
         return  low;
    }
6.冒泡
public   void  bubbleSort( int [] array){
for ( int  i=0;i<array. length ;i++){
       for ( int  j=0;j<array. length -1-i;j++){
         if (array[j]>array[j+1]){
           int   tmp  = array[j];
   Array[j] = array[j+1];
  Array[j+1] = tmp; //交换j和j+1
        }
      }
    }
}
7.归并:时间复杂度是O(nlogn),空间复杂度 O(n) ,稳定的。
将已有序的子序列合并,得到完全有序的序列。将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。
public   static   void  sort( int [] data, int  left, int  right) {  
         if  (left >= right)  
             return ;  
         // 找出中间索引  
         int  center = (left + right) / 2;  
         // 对左边数组进行递归  
         sort (data, left, center);  
         // 对右边数组进行递归  
         sort (data, center + 1, right);  
         // 合并  
         merge (data, left, center, right);  
    }  
     public   static   void  merge( int [] data, int  left, int  center, int  right) {  
         // 临时数组  
         int [] tmpArr = new   int [data. length ];  
         // 右数组第一个元素索引  
         int  mid = center + 1;  
         // third 记录临时数组的索引  
         int  third = left;  
         // 缓存左数组第一个元素的索引  
         int  tmp = left;  
         while  (left <= center && mid <= right) {  
             // 从两个数组中取出最小的放入临时数组  
             if  (data[left] <= data[mid]) {  
                tmpArr[third++] = data[left++];  
            } else  {  
                tmpArr[third++] = data[mid++];  
            }  
        }  
         // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)  
         while  (mid <= right) {  
            tmpArr[third++] = data[mid++];  
        }  
         while  (left <= center) {  
            tmpArr[third++] = data[left++];  
        }  
         // 将临时数组中的内容拷贝回原数组中  
         // (原left-right范围的内容被复制回原数组)  
         while  (tmp <= right) {  
            data[tmp] = tmpArr[tmp++];  
        }  
    }  
8.基数:
public static void sort(int[] number, int d) //d表示最大的数有多少位
    {
        intk = 0;
        intn = 1;
        intm = 1; //控制键值排序依据在哪一位
        int[][]temp = newint[10][number.length]; //数组的第一维表示可能的余数0-9
        int[]order = newint[10]; //数组orderp[i]用来表示该位是i的数的个数
        while(m <= d)
        {
            for(inti = 0; i < number.length; i++)
            {
                intlsd = ((number[i] / n) % 10);
                temp[lsd][order[lsd]] = number[i];
                order[lsd]++;
            }
            for(inti = 0; i < 10; i++)
            {
                if(order[i] != 0)
                    for(intj = 0; j < order[i]; j++)
                    {
                        number[k] = temp[i][j];
                        k++;
                    }
                order[i] = 0;
            }
            n *= 10;
            k = 0;
            m++;
        }
    }
 
9.折半查找方法适用于不经常变动而查找频繁的有序列表。






  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值