java数据结构:排序算法(1)

原创 2016年05月31日 20:02:38
package com.sort;


//本节学习几种常见的排序方式:
/*1.排序简介:
 *  排序可以分为内部排序和外部排序,
 * 2.内部排序:(只使用内存进行排序)
 *      2.1插入排序:
 *          直接插入排序;
 *          希尔排序;
 *      2.2交换排序:
 *          冒泡法排序
 *          快速排序
 *      2.3选择排序
 *          简单选择排序
 *          堆排序
 *      2.4 基数排序
 *      2.5 归并排序
 *      2.6桶排序
 * ----由于对树没有一个全面的体系,在此把 2.3-2.6的内容作为下一次学习的内容---
 * */

//2.1直接插入排序;
//参考文献: http://developer.51cto.com/art/201206/345156.htm
class InsertSort {
    /*直接插入排序的基本思想:(从小到大)
     * 把待排序的记录按其关键字的大小逐个插入到一个已经排好序的有序序列中,直到
     * 所有的记录插入完成为止,得到一个新的有序序列;
     * 第一步:
     *      从第一个元素开始,该元素可以认为已经被排序;
     * 第二步:
     *      取出下一个元素,在已经排序的元素序列中  从后向前  扫描比较;
     * 第三步:  
     *      如果该元素(已排序)大于新元素,将该元素移到下一位置
     * 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置  将新元素插入到该位置中  
     * 重复步骤2至到结束;
     * 
     * 性能分析:
     * 为了正确的插入第i个记录,最多要比较i次,最少比较1次,那么平均比较(i/2)次,总共是 从第2个到第n个数
     * 所以总的比较次数:sum(i=2:n;i/2) =(n2/4)
     * 空间复杂都:O(1);
     * */
    /**
     * @param arr:要进行排序的数组
     */
    public static void directInsertSort(int[] arr){
        //1.拿到数组长度:
        int len = arr.length;
        int temp,j;
        //2.外层循环遍历要进行插入的无序元素;
        for(int i=1;i<len;i++){
            temp = arr[i];
            j = i-1;
            //内部循环判断:这个无序元素与有序序列的比较,从后向前;
            while(j>=0 && temp<arr[j]){
                arr[j+1] = arr[j];
                j--;
            }
            arr[j+1] = temp;
        }
    }
    /**
     * @param arr:要进行排序的数组
     * @param n:要进行排序数组中的元素个数
     */
    public static void directInsertSort(int[] arr,int n){
        int temp, j;
        //依次取出要进行排序的元素,我们默认第一个元素排好了序,因此int i =1;
        for(int i=1;i<n;i++){
            temp = arr[i];
            //这是第二步:从后向前遍历已经排好序的元素,和这个新元素一一比较;
            for(j=i-1;j>=0 && temp<arr[j];j--)
                arr[j+1] = arr[j];
            arr[j+1]= temp;
        }
    }


    /*希尔排序的基本思想:
     * 选定一个增量d<n,把全部记录按此值从第一个记录其进行分组,所有相距为d的记录作为一组;
     * 现在各个组内进行插入排序,然后减小间隔,取第二个增量d2<d;重复上述分组和排序过程,直至
     * di=1;即所有的记录放在同一组内排序;
     * 
     * 第一步:先将元素按某个增量d分成若干组,每组中的成员是由角标相差d的元素组成的,
     * 第二步:对每组中的元素进行 直接插入排序;
     * 第三步:缩减d使其以一个较小的增量再进行分组,
     * 第四步:重复1 2 3直到d=1;
     * 
     * 性能分析:
     * 希尔排序时间复杂都大约为 n的1.3次方;
     * */
    public static void shellSort(int[] arr,int n){  
        double d1=n;  
        int temp=0;  
        while(true){  
            d1= Math.ceil(d1/2); //防止出现d 等于0的时候这样程序就挂在哪里;
            int d=(int) d1;  
            //第分成的 d 组进行各自的直接插入排序;
            for(int x=0;x<d;x++){  
                int j;
                //每组内进行直接插入排序(注意每组中的成员是角标相差d的元素组成的);
                for(int i=x+d;i<n;i=i+d){ 
                    temp=arr[i];  
                    //和本组中已经排好序的元素,进行从后向前的扫描;
                    for(j=i-d;j>=0 && temp<arr[j];j=j-d){  
                        arr[j+d]=arr[j];  
                    }  
                    arr[j+d]=temp;  
                }  
            }  
            if(d==1)  
                break;  
        }  
    }  
}

//2.交换排序
class ChangeSort{
    /*1.冒泡排序的基本思想:
     *  通过相邻的记录的两两比较和交换,使关键字较小的记录如同水泡一样逐步向上漂浮(数组头)
     *  而关键字较大的记录好比石头一样往下沉,每一趟,都有最大的一块石头沉入水底;
     * 基本思路:
     * 先将一个记录的关键字和第二个记录的关键字进行比较,若为逆(左边小于右边),则交换两个记录
     * 然后比较第二个记录和第三个记录,……如此下去,直到第n个和第n-1个进行比较,
     * 算法实现:
     *  第一步:先把最大的元素放到最后;
     *  第二步:在把前 n-1个元素进行第一步操作;
     *  第三步:重复 直到n=1;
     * 
     * 性能:
     * 总的时间复杂度O(n2)
     * 
     * */
    public static void bubbleSort(int[] arr,int n){
        //n个元素的一组数据进行排序;
        int temp;
        for(int i=0;i<n;i++){
            //把这组元素中 数值最大的放到最后
            for(int j=0;j<n-1;j++){
                if(arr[j]>arr[j+1]){
                    temp =arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
            //让组中的元素个数减 1;
            n--;
        }
    }

    /*
     * 2.快速排序
     *  快速排序是对冒泡的一种改进,冒泡中记录的比较和交换是在相邻的单元中进行的;记录
     *  每次交换只能上移或者下移一个单元,因而总的比较和移动次数较多,快速排序改进后,
     *  让记录的比较和交换从两端向中间进行,关键字较小和较大的记录一次就能换到前面和后面;
     *  基本思路:
     *      在待排序的n个记录中任选一个记录,通常取第一个记录,以该记录的关键值为基准,
     *      用交换的方式将所有的记录分成两部分,所有关键字比它小的记录,均排在它的之前,
     *      所有关键字比它大的都排在它的后面,这样就完成了一次排序,然后对分出的两个部分
     *      再进行上述排序,直到每部分只有一个记录为止,排序结束;
     *  待排序记录:r[t] r[t+1] r[t+2]......r[w-1] r[w];
     *  算法思路:
     *      第一步:设置两个变量 i ,j ,确定第一个记录为基准记录并让i为r[t]的脚标,
     *              j为r[w]的脚标
     *      第二步:先从j 所指示的位置向前扫描,当r[t]>r[j]时,交换r[t] 和 r[j].
     *              使关键字值比基准记录的关键字值小的记录交换到前面;
     *      第三步:从i所指示的位置向后扫描,直到 r[t]<r[i] 交换
     *      第四步:重复上述 2,3直到i=j;为一趟排序
     * */

    public static void quickSort(int[] arr, int low, int high) {
        int temp;
        int i,j;
        if(low<high){
            i = low;
            j= high;
            temp =arr[i];
            //进行一趟排序直到 i= j结束
            while(i<j){

                //j 向左扫描,直到找到关键字值比基准记录的值小的记录;
                while(i<j && (arr[j]>=temp)){
                    j--;
                }
                //找到,则交换arr[i]和arr[j]的位置,并让 i 指向后一个元素
                if(i<j){
                    arr[i] = arr[j];
                    i++;
                }

                //i 向右扫描,直到找到关键字值比基准记录的值大的记录;
                while(i<j && arr[i]<=temp){
                    i++;
                }
                //找到,则交换arr[i]和arr[j]的位置,并让 j指向前移动一个元素
                if(i<j){
                    arr[j] = arr[i];
                    j--;
                }       
            }
            arr[i] = temp;
            //递归处理左区间:
            quickSort(arr,low,j-1);
            //递归处理右区间
            quickSort(arr,j+1,high);
        }
    }




    public static void quickSort(int[] a) {
        if(a.length>0){
            quickSort2(a,0,a.length-1);
        }
    }
    private static void quickSort2(int[] a, int low, int high) {
        if(low<high){ 
            int middle = getMiddle(a,low,high);
            quickSort(a, 0, middle-1);
            quickSort(a, middle+1, high);
        }
    }

    private static int getMiddle(int[] a, int low, int high) {
        int temp = a[low];//基准元素
        while(low<high){
            //找到比基准元素小的元素位置
            while(low<high && a[high]>=temp){
                high--;
            }
            a[low] = a[high]; 
            while(low<high && a[low]<=temp){
                low++;
            }
            a[high] = a[low];
        }
        a[low] = temp;
        return low;
    }

}


//选择排序
/*选择排序是指每次从待排序的记录中选择出关键字值最小(最大)的记录,顺序放在已经排好
 * 顺序的有序序列中,直到全部排完;
 * 
 * */
class SelecteSort{
    /*1.简单选择排序;
     * 基本思想:
     *  对待排序的数组,进行n-1趟扫描,第i趟扫描选出剩下的n-i+1个记录中关键字值最小的记录
     *  和第i个记录交换,:
     *  第一次排序空间:r[1] - r[n] 把经过比较和交换后 把最小的元素放在r[1]中,
     *  第二次排序空间:r[2] - r[n] 经过选择和交换后,r[2]中放次小的记录,
     *  .....
     * 
     * */
    /**
     * @param arr:要进行简答选择排序的数组
     * @param n:数组中的前多少项元素进行排序;
     */
    public static void simpleSelecteSort(int[] arr,int n){
        int temp;
        for(int i=0;i<n;i++){
            int position = findMin(arr,i,n);
            //将最小的元素和起始元素发生交换;
            temp = arr[i];
            arr[i] = arr[position];
            arr[position] = temp;
        }
    }
    /**
     * @return :元素值最小的角标
     */
    private static int findMin(int[] arr,int low,int high){
        int position = low;
        for(int i=low+1;i<high;i++){
            if(arr[i]<arr[position])
                position = i;
        }
        return position;
    }


}



其各个函数运行结果,本人已经验证过了木有问题的;

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java数据结构与算法之常见排序算法总结

目录: 1.概述 2.常用排序方法总结 3.冒泡排序 4.选择排序 5.插入排序 6.归并排序 7.快速排序 8.shell排序 1.概述 学过排序算法的朋友可能都知道排序算法...
  • qq_28057577
  • qq_28057577
  • 2016年10月08日 15:54
  • 528

数据结构几种排序算法详解和总结(java版)

一、排序的概念: 1、设 n 个记录的序列为  { R1 , R2 , R3 , . . . , Rn} 其相应的关键字序列为  { K1 , K2 , K3, . . . , Kn } 若规定 1...
  • u011067360
  • u011067360
  • 2013年12月30日 17:42
  • 2586

【数据结构】几种常见的排序算法

一、排序算法的分类     下图是我掌握的一些排序算法,我将他们做了分类,当然,排序算法远不止这些。 本篇博客主要记录插入,选择,以及交换排序的冒泡排序,因为快排和归并算法相对复杂,所以,...
  • pointer_y
  • pointer_y
  • 2016年11月26日 23:06
  • 1389

【数据结构排序算法系列】数据结构八大排序算法

排序算法在计算机应用中随处可见,如Windows操作系统的文件管理中会自动对用户创建的文件按照一定的规则排序(这个规则用户可以自定义,默认按照文件名排序)因此熟练掌握各种排序算法是非常重要的,本博客将...
  • htq__
  • htq__
  • 2016年03月25日 22:36
  • 94214

重学数据结构系列之——八大排序算法

一、有一种分类 稳定排序:如果线性表中的两个元素 a​i 和 aj​​  满足 i 简单来说就是排序前有两个或多个相等的元素,排序后他们的相对位置不会改变) 不稳定排序:不是上面的情况就是了 ...
  • u012763794
  • u012763794
  • 2016年04月19日 23:11
  • 2276

算法经典面试题整理(java实现)

以下从Java角度解释面试常见的算法和数据结构:字符串,链表,树,图,排序,递归 vs. 迭代,动态规划,位操作,概率问题,排列组合,以及一些需要寻找规律的题目。 1. 字符串和数组 字符...
  • DUANJIEFEI
  • DUANJIEFEI
  • 2015年06月11日 19:23
  • 9518

数据结构与算法-----冒泡排序

冒泡排序 1)算法 A.比较相邻的元素,如果第一个比第二个大就交换它们; B.对每一对相邻的元素都做同样的工作,从开始的第一对到结尾的最后一对。经过这一步,最后的元素是最大值; C.针对所有的...
  • u010193457
  • u010193457
  • 2015年12月02日 16:10
  • 1866

数据结构之排序算法(二)-冒泡排序及改进

冒泡排序算法需要遍历几次数组。每次遍历都要比较连续相邻的元素,如果某一对相邻元素是降序,则互换它们的值,否则,保持不变。由于较小的值像“气泡”一样逐渐浮想顶部,而较大的值沉向底部,所以叫冒泡排序。 ...
  • tuke_tuke
  • tuke_tuke
  • 2015年12月21日 15:10
  • 2058

数据结构的各种排序算法稳定性比较

一、前面有讲到了9种排序算法:1.简单选择排序 2.堆排序 (1和2是属于选择排序)3.直接插入排序 4.希尔排序 (3和4属于插入排序,有时把改进后的直接插入排序叫做二分插入)...
  • u010889616
  • u010889616
  • 2015年08月19日 11:06
  • 1974

数据结构与算法--查找与排序(一)

Top 线性查找二分查找冒泡排序插入排序选择排序快速排序归并排序 1 线性查找 1.1 问题 线性查找,又称为顺序查找,是指在所有给定的值中从一端开始逐个检查每个元素是否为要查...
  • opera95
  • opera95
  • 2016年04月22日 08:30
  • 2746
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java数据结构:排序算法(1)
举报原因:
原因补充:

(最多只允许输入30个字)