zoukankan      html  css  js  c++  java
  • 八大算法手写

    一、八大排序简介

    1. 插入排序(直接插入排序,二分插入排序,shell排序)
    2. 交换排序(冒泡排序,快速排序)
    3. 选择排序(直接选择排序,堆排序)
    4. 归并排序
    5. 分配排序(基数排序)

    1. 插入排序

    思想:将每一个待排序序列,每一步都按顺序码插入到前面已经排序的子序列中,直到全部插入排序完为止。

    /**
    * 直接插入排序
    * 思想:两次for循环,时间复杂度:O(n^2),空间复杂度:O(1)
    * @param a
    * @return
    */
    public static int[] insertionSortDirect(int []a){
        for(int j=1;j<a.length;j++){
            int t=a[j];//待插入元素
            int i;
            for(i=j-1;i>=0 && a[i]>t;i--){
                a[i+1]=a[i];//将大于插入元素的往后移动一位
            }
            a[i+1]=t;
        }
        return a;
    }
    /**
    * 二分插入排序
    * 思想:按照折半查找,减少查找次数;时间复杂度:O(nlog2n);空间复杂度:O(1)
    */
    public static int[] insertionSortTwo(int []a){
        for(int i=1;i<a.length;i++){
           int t=a[i],right=i-1,left=0,mid;
        while(right>=left){
          mid
    =(right+left)/2;
          if(a[mid]<t){
            left
    =mid+1;
          }
    else{
            right
    =mid-1;
          }
        }
         for(int j=i-1;j>=left;j--){
           a[j
    +1]=a[j];//移动元素
         }
         if(left!=i){
           a[left]
    =t;
         }
        }
      return a;
    }

    2.Shell排序

    /**
    * Shell排序
    * 相当于分组排序,将间隔dk的元素放在同一组里,进行排序,时间复杂度:O(nlog2n);空间复杂度:O(1)
    */
    public static int[] insertSortShell(int a[],int i){
        int dk=a.length/i;
        while(dk>=1){
            insertShell(a, dk);
            dk=dk/2;
        }
        return a;
    }
    public static void insertShell(int a[],int dk){
        for(int j=1;j<a.length;j++){
            int t=a[j];//待插入元素
            int i;
            for(i=j-dk;i>=0&&a[i]>t;i=i-dk){
                    a[i+dk]=a[i];//将大于插入元素的往后移动一位
            }
            a[i+dk]=t;
        }
    }

    3.简单选择排序

    /**
     * 简单选择排序
     * 思想:通过一次循环,找到最小值的下标,把最小值放在最前面,再在后面的数中继续寻找,直到倒数第二个
     */
    private static void simpleSelectSort(int []a){
        int min;
        for(int i=0;i<a.length-1;i++){
            min=i;
            for(int j=i+1;j<a.length;j++){//找到最小值得下标
                if(a[j]<a[min]){
                    min=j;
                }
            }
            swap(a,i,min);
        }
    }
    private static void swap(int a[],int i,int min){
        if(i==min){
            return;
        }
        a[i]+=a[min];
        a[min]=a[i]-a[min];
        a[i]=a[i]-a[min];
    }
    /**
    * 二元选择排序
    * 思想:与简单选择排序不同的是分别找出最大和最小
    */
    private static void binarySelectSort(int []a){
        int max,min;
        for(int i=0;i<a.length/2;i++){
            min=max=i;
            for(int j=i+1;j<a.length-i;j++){
               if(a[j]<a[min]) {
            min=j;
              continue; } if(a[j]>a[max]) max=j; } swap(a, i, min); swap(a, a.length-i-1, max);
    }

    4. 改进的冒泡排序

    /**
    * 改进的冒泡排序
    */
    private static void buddle(int []a){
        int high=a.length-1,low=0;
        while(low<high){
            for(int i=low;i<high;i++){
                if(a[i]>a[i+1]){
                    swap(a,i,i+1);
                }
            }
            for(int i=high;i>low;i--){
                if(a[i]<a[i-1]){
                    swap(a,i,i-1);
                }
            }
            ++low;
                    --high;
        }
    }
    private static void swap(int[] a, int i, int j) {
        if(i==j) return;
        a[i]+=a[j];
        a[j]=a[i]-a[j];
        a[i]=a[i]-a[j];
    }

    5.堆排序

    /**
    堆排序
    *思想:是一种树形结构,是对直接选择排序的有效改进。
    *堆的定义如下:
    *具有n个元素的序列(k1,k2,…,kn),当且仅当满足下面条件时称之为堆。
    *Ki>=K2i,Ki>=K2i+1//Ki<=K2i,Ki<=K2i+1;
    *初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个堆,
    *这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。
    *依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,
    *一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。
    */
    public static void heapSort(int a[]){
        for(int i=0;i<a.length;i++){
            createMaxHeap(a,a.length-i);//创造最大的堆
            swap(a, 0, a.length - 1 - i);
            }
    }
    private static void swap(int[] a, int i, int j) {
        if(i==j) return;
        a[i]+=a[j];
        a[j]=a[i]-a[j];
        a[i]=a[i]-a[j];
    }
    private static void createMaxHeap(int[] a, int lastIndex) {
        //从最后一个节点lastIndex的父节点开始
        for(int i=(lastIndex-1)/2;i>=0;i--){
            int k=i;// 保存当前正在判断的节点
            while(2*k+1<lastIndex){// bigIndex总是记录较大节点的值,先赋值为当前节点的左子节点的索引
                int bigIndex = 2*k+1;
                if(bigIndex+1<lastIndex){
                    if (a[bigIndex] < a[bigIndex + 1]) {// 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的索引
                                bigIndex++;
                            }
                }
                // 如果k节点的值小于其较大的子节点的值
                if (a[k] < a[bigIndex]) {
                    // 交换两者的值
                    swap(a, k, bigIndex);
                    // 将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
                    k = bigIndex;
                } else {
                    break;
                }
            }
        }
    }

    6.归并排序

    /**
     * 归并排序
     *思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列.
    */
    private static void sort(int []q,int left,int right) {
        if(left<right){
            int center=(left+right)/2;
            sort(q,left,center);
            sort(q,center+1,right);
            marge(q,left,center,right);
        }
    }
    private static void marge(int[] q, int left, int center, int right) {
        int third[]=new int[q.length];
        int mid=center+1;
        int tleft=left;
        int tem=left;
        while(left<=center&&mid<=right){
            if(q[left]<=q[mid]){
                third[tleft++]=q[left++];
            }else{
                third[tleft++]=q[mid++];
            }
        }
        while(mid<=right){
            third[tleft++]=q[mid++];
        }
        while(left<=center){
            third[tleft++]=q[left++];
        }
        while(tem<=right){
            q[tem]=third[tem++];
        }
    }

    7. 快速排序

    /**
     * 快速排序
     * 思想:基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,
     * 此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
    */
        private static void quickSort(int []a,int low,int high){
            if(low<high){
                int mid=getMiddle(a, low, high);
                quickSort(a, low, mid-1);
                quickSort(a, mid+1, high);
            }
        }
        private static int getMiddle(int []a,int low,int high){
            int tem=a[low];
            while(low<high){
                while(low<high&&a[low]<=tem){
                    low++;
                }
                a[low]=a[high];
                while(low<high&&a[high]>=tem){
                    high--;
                }
                a[high]=a[low];
            }
            a[low]=tem;
            return low;
        }    

    8.基数排序

    /**
     * 基数排序
     * 思想:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。
    这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列
    */ private static int[] radixSort(int[] a) { int max=a[0]; //首先确定排序趟数 for(int i=0;i<a.length-1;i++){ if(a[i]>max) max=a[i]; } int t=0; while(max>0){ max/=10; t++;//位数} //建立十个队列 ArrayList<ArrayList<Integer>> arr=new ArrayList<>(); for(int i=0;i<10;i++){ ArrayList<Integer> queue=new ArrayList<>(); arr.add(queue); } //进行t次收集和处理 for(int i=0;i<t;i++){ //分配数组元素 for(int as:a){ //得到数据的第t+1位的数 int x= as%(int)Math.pow(10, i+1)/(int)Math.pow(10, i); ArrayList<Integer> que=arr.get(x); que.add(as); arr.set(x, que); } int count=0;//元素计数器 for(int k=0;k<10;k++){ while(arr.get(k).size()>0){ ArrayList<Integer> q=arr.get(k); a[count]=q.get(0); q.remove(0); count++; }
            }
          }
    return a; }
  • 相关阅读:
    PL/SQL基础
    Oracle数据库安装与卸载
    数据结构与算法学习(四):树
    数据结构与算法学习(三):算法经典问题
    数据结构与算法学习(二):栈和队列
    数据结构与算法学习(一):线性表
    NodeJS+axios上传图片
    WCF可靠性会话之服务分流
    MVC的局部视图传参的小技巧--见人才网头部导航
    MVC分层处理
  • 原文地址:https://www.cnblogs.com/chen2608/p/12683089.html
Copyright © 2011-2022 走看看