学习笔记-算法-6-排序

18 篇文章 0 订阅

算法&数据结构

基本概念

  • data structure

    • 存储数据的方式
  • algorithm

    • 解决方法
  • 算法优劣

    • 时间
    • 空间
  • 时间复杂度

    • 随着规模的扩大时间的变化
  • 空间复杂度

    • 随着规模的扩大空间的变化

排序

冒泡排序

  • 相邻的两个元素逆序,就需要交换
public static void main(String[] args){
    int[] arr = {5,3,4,2,1,7,6,9,8};
    sort(arr);
    print(arr);
}

public static void sort(int[] arr){
    for(int i=arr.length-1;i>0;i--){
        for(int j=0;i<arr.length-1-i;j++){
            if(arr[j]>arr[j+1]){
                swap(arr,j,j+1);
            }
        }
    }
}

public static void swap(int[] arr,int i,int j){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

public static void print(int[] arr){
     for(int i=0;i<arr.length;i++){
        System.out.print(arr[i]+'" ");
    }
}
优化
public static void main(String[] args){
    int[] arr = {5,3,4,2,1,7,6,9,8};
    boolean flag = false;       //标识 是否进行过交换
     for(int i=arr.length-1;i>0;i--){
        for(int j=0;i<arr.length-1-i;j++){
            if(arr[j]>arr[j+1]){
                flag = true;
                swap(arr,j,j+1);
            }
        }
        if(!flag){
            // 一次交换也没发生,已经排序完成
            break;
        }else{
            flag = false;   // 重置
        }
    }
    print(arr);
}



public static void swap(int[] arr,int i,int j){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

public static void print(int[] arr){
     for(int i=0;i<arr.length;i++){
        System.out.print(arr[i]+'" ");
    }
}

选择排序

  • 选择排序
    • 简单
    • 不稳定
public static void main(String[] args){
    int[] arr = {5,3,4,2,1,7,6,9,8};
    sort(arr);
    print(arr);
}

public static void sort(int arr){
    for(int i=0;i<arr.length-1;i++){
        int minPos = i;
        for(int j=i+1;j<arr.length;j++){
            if(arr[j]<arr[minPos]){
                minPos = j;
            }
        }
        swap(arr,i,minPos);
    }
}

public static void swap(int[] arr,int i,int j){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

public static void print(int[] arr){
     for(int i=0;i<arr.length;i++){
        System.out.print(arr[i]+'" ");
    }
}

插入排序

public static void main(String[] args){
    int[] arr = {5,3,4,2,1,7,6,9,8};
    sort(arr);
    print(arr);
}

public static void sort(int[] arr){
    for(int i=1;i<arr.length;i++){
        for(int j=i;j>0;j--){
            if(arr[j]<arr[j-1]){
                swap(arr,j,j-1);
            }
        }
    }
}

public static void swap(int[] arr,int i,int j){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

public static void print(int[] arr){
     for(int i=0;i<arr.length;i++){
        System.out.print(arr[i]+'" ");
    }
}

希尔排序

  • 在局部排序时可以采用插入或者交换方法排序
public static void main(String[] args){
    int[] arr = {5,3,4,2,1,7,6,9,8,0};
    sort(arr);
    print(arr);
}

public static void sort(int[] arr){
    int h=1;
    while(h<=arr.length/3){
        h=h*3+1;
    }

    for(int gap=h;gap>0;gap =(gap-1)/3){
        for(int i=gap;i<arr.length;i++){
            for(int j=i;j>gap-1;j-=gap){
                if(arr[j]<arr[j-gap]){
                    swap(arr,j,j-gap);
                }
            }
        }
    }
}

public static void swap(int[] arr,int i,int j){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

public static void print(int[] arr){
     for(int i=0;i<arr.length;i++){
        System.out.print(arr[i]+'" ");
    }
}

快速排序

  • 单轴快排
  • 双轴快排
public static void main(String[] args){
    int[] arr = {5,3,4,2,1,7,6,9,8};
    sort(arr,0,arr.length-1);
    print(arr);
}

public static void sort(int[] arr,int leftBound,int rightBound){
    if(leftBound>=rightBound) return;
    int mid = partition(arr,leftBound,rightBound);
    sort(arr,leftBound,mid-1);
    sort(arr,mid+1,rightBound);
}

public static int partition(int[] arr,int leftBound,int rightBound){
    int pivot = arr[rightBound];
    int left = leftBound;
    int right = rightBound - 1;
    while(left <= right){
        while(left<=right&& arr[left] <= pivot) left++;
        while(left<=right&& arr[right]> pivot) right--;
        if(left < right) swap(arr,left,right);
    }
    swap(arr,left,rightBound);
    return left;
} 

public static void swap(int[] arr,int i,int j){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

public static void print(int[] arr){
     for(int i=0;i<arr.length;i++){
        System.out.print(arr[i]+'" ");
    }
}

归并排序

public class QuickSort{
    public static void main(String[] args){
        int[] arr = {-9,78,0,23,-567,70};
        quickSort(arr,0,arr.length-1);
    }
    
    public static void quickSort(int[] arr,int left,int right){
        int l = left;   // 左下标
        int r = right;  // 右下标
        int pivot = arr[{left+right}/2];    //中轴
        int temp = 0;   // 临时变量,交换时使用
        // while循环目的时让比pivot值小的放左边
        while(l<r){
            // 在左边一致找,找到大于等于pivot的值,才退出
            while(arr[r]<pivot){
                l+=1;
            }
            // 在右边一致找,找到小于等于pivot的值,才退出
            while(arr[r]>pivot){
                r-=1;
            }
            // 如果l>=r,说明左右两边值已经全部满足要求
            if(l>=r){
                break;
            }
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            
            // 简化完后发现arr[l]==pivot值
            if(arr[l]==pivot){
                r -= 1;
            }
            if(arr[r]==pivot){
                l += 1;
            }
        }
        if(l==r){
            l += 1;
            r -= 1;
        }
        if(left<r){
            quickSort(arr,left,r);
        }
        if(right>1){
            quickSort(arr,r,right);
        }
    }
}

归并排序

  • 分治策略
public class MergetSort{
    pulic static void main(String[] args){
        int arr[] = {5,4,6,7,3,7,2};
        int temp[] = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        
    }
    
    // 分+合
    public static void mergeSort(int[] arr,int left,int right,int[] temp){
        if(left < right){
            int mid = (left + right) /2;// 中间索引
            // 向左递归
            mergeSort(arr,left,mid,temp);
            // 向右递归
            mergeSort(arr,mid+1,right,temp);
            // 合并
            merge(arr,left,mid,right,temp);
        }
    }
    
    // 合并
    // arr 排序原始数组
    // left 左边有序序列初始索引
    // mid 中间索引
    // right 右边最后段索引
    // temp 中转数组
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i=left;         // 左边有序序列初始索引
        int j = mid + 1;    // 右边有序序列初始索引
        int t = 0;          // 指向temp当前索引
        
        // 先把左右两边数据按规则填充到temp中
        while(i<=mid && j <= right){
            if(arr[i]<=arr[j]){
                temp[t] = arr[i];
                t += 1;
                i += 1;
            }else{
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }
        // 把剩余的数据一边全部填充到temp中
        while(i<=mid){
            // 左边剩余
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }
        while(j<= right){
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }
        // 剩余的元素拷贝到arr
        t = 0;
        int tempLeft = left;
        while(tempLeft <= right){
            arr[tempLeft] = temp[t];
            tempLeft += 1;
            t += 1;
        }
    }
}

基数排序

  • 桶排序
    • 按个位分桶
    • 按桶依次取出放回原数组中
    • 按十位分桶
    • 按桶依次取出放回原数组中
    • 按百位分桶
    • 按桶依次取出放回原数组中
    • 。。。
public class RedixSort{
    public static void main(String[] args){
        int[] arr = {53,3,542,754,14,214};
        radixSort(arr);
    }
    
    
    public static void radixSort(int[] arr){
        // 获取最大位数
        int max = arr[0];
        for(int i=0;i<arr.length;i++){
            if(arr[i]>max){
                max = arr[i];
            }
        }
        int maxLength = (max+"").length();
        // 空间换时间 
        int[][] bucket = new int[10][arr.length];
        // 记录各桶存放数据
        int[] bucketElementCounts = new int[10];
        for(int i=0,n=1;i<maxLength;i++,n*=10){
            for(int j=0;j<arr.length;j++){
                // 取出每个元素个/十/百位数
                int digitOfElement = arr[j]/n%10;
                // 放入对应桶
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
                bucketElementCounts[digitOfElement]++ ;
            }
            
            // 按照这个桶顺序重新放入原数组
            int index = 0;
            for(int k=0; k<bucketElementCounts.length;k++){
                // 如果桶中有数据,存入原数组中
                if(bucketElementCounts[k]!=0){
                    // 第k个桶
                    for(int l=0;l<bucketElementCounts[k];k++){
                        arr[index] = bucket[k][l];
                        index++;
                    }
                    bucketElementCounts[k] = 0;
                }
            }
        }
        
    }
    
}


计数排序

  • 计数数组
public static void main(String[] args){
    int[] arr = {5,3,4,2,1,7,6,9,8,0,2,3,3,5,6,2,3,1,2,0,4,6,7,8,9,8};//0~9
    int [] result = sort(arr);
    System.out.println(Arrays.toString(result));
}

public static int[] sort(int[] arr){
    int[] result = new int[arr.length];
    int[] count = new int[10];
    
    for(int i=0;i<arr.length;i++){
        count[arr[i]]++;
    }
    
    System.out.println(Arrays.toString(count));
    /*
    for(int i=0,j=0;j<count.length;j++){
        while(count[i]-->0) result[i+1] = i ;
    }
    */
    for(int i=1;i<count.lenght;i++){
        count[i] = count[i]+count[i-1];
    }
    System.out.println(Arrays.toString(count));
    for(int i=arr.leingth-1;i>=0;i--){
        result[--count[arr[i]]] = arr[i];
    }
    
    return result;
    
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值