Java实现基本排序算法的示例代码

目录
  • 1. 概述
  • 2. 插入排序
    • 2.1 直接插入排序
    • 2.2 希尔排序(缩小增量排序)
  • 3. 选择排序
    • 3.1 直接选择排序
    • 3.2 堆排序
  • 4. 交换排序
    • 4.1 冒泡排序
    • 4.2 快速排序
  • 5. 归并排序
  • 6. 计数排序(非比较类型的排序)
  • 7. 排序算法总结

1. 概述

排序概念:就是将一串记录按照其中某个或某些关键字的大小,递增或递减的排列起来的操作。

稳定性:通俗的将就是数据元素不发生有间隔的交换,例如:

内部排序:数据元素全部放在内存中的排序

外部排序:数据元素太多不能一次加载到内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

注意:以下的排序默认排升序。默认待排序列为:2,5,1,3,8,6,9,4,7,0,6

2. 插入排序

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列

2.1 直接插入排序

1. 思想:

对于一个元素,将其与前面元素进行比较,将其插入到合适的位置。

排升序:将待排元素依次与序列中元素从右往左比,若待排元素小,则继续往前比,找到合适位置插入,原来元素的位置按顺序往后搬移。

2. 画图说明:

说明:第一个元素默认它有序,所以从第二个元素开始进行比较然后插入,5比2大,继续下一个,将1依次比较插入2前面,将3依次比较插入5前面,8比5大,不用管,继续下一个,将6依次比较插在8面,9比8大,不用管,将7依次比较,插在8前面,将0依次比较插在1前面,将6依次比较插在7前面,插入完成。

3.代码展示:

public class InsertSort {
    public static void insertSort(int[] array){
        for(int i = 1;i < array.length;i++){    //让从1下标开始,因为如果只有一个元素,它自己默认有序
            int key = array[i];          //从数组中的第二个元素开始比较,进行插入
            int end = i-1;        //end的位置是要插入元素的前一个位置
            while(end >= 0 && key < array[end]){    //end不能越界,找待插入的位置,此处注意:key不能小于等于array[end],否则为不稳定
                array[end+1] = array[end];
                end--;
            }
            array[end+1] = key;         //找到位置进行插入,因为上面end--了,所以这里要插入的位置为end+1
        }
    }

    public static void main(String[] args) {
        int[] array = {2,5,1,3,8,6,9,4,7,0,6};
        insertSort(array);
        for(int i : array){
            System.out.print(i+" ");
        }
    }
}

结果:

4.特性总结:

时间复杂度:循环嵌套,O(N^2),最优情况:当序列接近有序,插入的元素比较少,为O(N)

空间复杂度:不借助辅助空间,O(1)

稳定性:数据元素不发生有间隔的交换,稳定

应用场景:数据量小,接近有序

2.2 希尔排序(缩小增量排序)

1. 思想:

选一个整数为数据元素的间隔,将间隔相同的数据元素分为一组,分别对这些组进行插入排序,间隔减小,重复上述操作,当间隔减少到1的时候,数据元素即排好序了。

2. 画图说明:

说明:gap为间隔,这里依次将gap=4,2,1,先把间隔为4的数据元素用插入排序排好序,再利用插入排序排gap=2 的数据元素,依次重复上述操作,即可。

3. 代码展示:

public class ShellSort {
    public static void shellSort(int[] array){
        int gap = array.length;
        while(gap > 1){
            gap = gap/3+1;
            for(int i = gap;i < array.length;i++){  //跟插入排序一样,都从一组数的第二个元素开始,因为第一个数默认有序
                int key = array[i];
                int end = i - gap;        //end的位置也是代排数的前一个,但这里间隔为gap,所以前一个位置为i-gap
                while(end >= 0 && key < array[end]){   //与插入排序保持不变,找待插入的位置
                    array[end+gap] = array[end];    // key小于前一个数,让end位置的元素往后移一位,
                    end -= gap;    //end每次向左走的时候一次走gap的间隔
                }
                array[end+gap] = key;    //找到待排位置将key插入相应位置
            }
        }
    }

    public static void main(String[] args) {
        int[] array = {2,5,1,3,8,6,9,4,7,0,6};
        shellSort(array);
        for(int i : array){
            System.out.print(i+" ");
        }
    }
}

结果:

4. 特性总结:

希尔排序是对直接插入排序的优化。

当gap>1时都是预排序,目的是让数组元素接近有序,当gap==1时,数组已经接近有序了,这样插入排序将会很快,整体而言,达到了优化的效果。

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算。

gap的取法有多种,最初shell提出取gap=n/2,gap=gap/2,直到gap=1,后来,Kunth提出取gap = [gap/3]+1。在Kunth所著的《计算机程序设计技巧》第3卷中,利用大量的实验统计资料得出,当n很大时,关键码的平均比较次数和对象平均移动次数大约在n^1.25到1.6n^1.25范围内,这是利用直接插入排序作为子序列排序方法的情况下得到的。

故时间复杂度暂记为:O(N^1.25)~O(1.6N^1.25)

空间复杂度:没有借助辅助空间,O(1)

稳定性:数据元素发生了有间隔的交换,不稳定

应用场景:数据比较随机

3. 选择排序

每一次从待排数据元素中选出最小(最大)的元素,存放在序列的起始(末尾)位置,直到全部待排序的数据元素全部排完。

3.1 直接选择排序

1. 思想:

思路1:

找出序列中的最大的元素,若它不在序列的末尾,将它与末尾元素交换位置,依次循环。

思路2:

每次找元素的时候,找一个最大的和一个最小的,最大的和最后一个交换位置,最小的和第一个交换位置,依次循环

2. 画图说明:

思路1:

说明:先找到序列的最大元素与序列最后一个元素交换,序列的最后的位置朝前移一个,再找新序列的最大元素再与最后一个交换位置,依次循环。

思路2:

说明:这种方法是一次找两个元素,跟上面那种本质上一样,只是一次交换了两个元素,将最大的与最后一个交换,将最小的与第一个交换

3. 代码展示:

public class SelectSort {
    public static void selectSort1(int[] array){
        int size = array.length;
        for(int i = 0;i < size-1;i++){   //选择的趟数,size-1是因为当选择到序列剩一个元素时就不用选了
            int pos = 0;    //pos标记最大元素的位置,刚开始是默认为第一个位置
            for(int j = 1;j < size-i;j++){   //j=1是因为默认第一个元素的位置为最大元素的位置,所以从第二个元素的位置开始比较
                                             //size-i是因为每趟选择完后,序列都要减少一个
                if(array[j] > array[pos]){
                    pos = j;    //找到最大元素位置,更新pos
                }
            }
            if(pos != size-i-1){   //如果最大元素的位置刚好是最后一个位置,则不需要交换,反之进行交换
                swap(array,pos,size-i-1);
            }
        }
    }
    public static void selectSort2(int[] array){
        int left = 0;     //序列的左边界
        int right = array.length-1;   //序列的右边界
        while(left < right){   //当序列中至少存在俩元素时
            int minPos = left;   //刚开始将最小元素的位置设定为序列的第一个位置
            int maxPos = left;   //刚开始将最大元素的位置也设定为序列的第一个位置
            int index = left+1;  //从序列的第二个元素开始找最大元素和最小元素的位置
            //找最大元素和最小元素的位置
            while(index <= right){
                if(array[index] < array[minPos]){
                    minPos = index;
                }
                if(array[index] > array[maxPos]){
                    maxPos = index;
                }
                index++;
            }
            if(minPos != left){  //当最小的元素不在序列的最左端时交换位置
                swap(array,minPos,left);
            }
            //这里我是先交换最小的元素,但是如果最大的元素在最左侧,那么会将maxPos位置的元素更新为最小的元素,导致后面
            //交换最大元素的时候maxPos标记的元素不准确,所以下面将maxPos的位置更新了一下
            //注意:如果是先交换最大的元素,则更新minPos的位置
            if(maxPos == left){
                maxPos = minPos;
            }
           // if(minPos == right){
           //     minPos = maxPos;
           // }
            if(maxPos != right){    //当最大元素不在序列的最右端时交换位置
                swap(array,maxPos,right);
            }
            left++;  //左边界+1
            right--; //右边界-1
        }
    }
    public static void swap(int[] array,int a,int b){
        int t = array[a];
        array[a] = array[b];
        array[b] = t;
    }

    public static void main(String[] args) {
        int[] array = {9,5,1,3,8,6,2,4,7,6,0};
        selectSort1(array);
        for(int i : array){
            System.out.print(i+" ");
        }
        System.out.println();
        selectSort2(array);
        for(int i : array){
            System.out.print(i+" ");
        }
    }
}

4:特性总结:

时间复杂度:找元素,交换元素是循环嵌套,O(N^2)

空间复杂度:没有借助辅助空间,O(1)

稳定性:数据元素存在有间隔的交换,不稳定

缺陷:找最大元素或者最小元素的时候重复比较

3.2 堆排序

1. 思想:

堆排序是利用堆积树(堆)这种数据结构设计的一种算法,它是选择排序的一种,它是通过堆来进行选择数据。

注意:排升序,建大根堆,排降序,建小根堆。

堆排序分为两部分:建堆,利用向下调整建堆,再利用堆删除的思想排序。

向下调整:

前提:要调整的节点的两个左右子树都已满足堆的特性

方法:建大堆,将根的元素与左右孩子较大的元素交换,建小堆,将根的元素与左右孩子较小的元素交换

堆删除思想:

将堆顶元素与最后一个元素交换位置

堆中有效元素减少一个

再对堆顶元素向下调整

2. 画图说明:

因为数据元素多,二叉树的图看着不太清晰,所以我用以下序列:0,5,3,4,1,2

建堆:

利用堆删除思想排序:

3. 代码展示:

public class HeapSort {
    //向下调整
    public static void shiftDown(int[] array,int parent,int size){
        int child = parent*2+1;  //默认将左孩子设为parent的孩子,因为不知道右边孩子是否存在
        while(child<size){
            if(child+1<size && array[child+1]>array[child]){   //如果右孩子存在,比较哪个孩子值大
                child += 1;   //将child设为较大的孩子
            }
            if(array[parent]<array[child]){  //如果parent小,将parent与child交换
                swap(array,parent,child);
                parent = child;   //更新parent
                child = parent*2+1;   //更新child
            }else{    //如果已经满足堆特性则直接返回
                return;
            }
        }
    }
    //堆排序
    public static void heapSort(int[] array){
        //建堆
        int size = array.length;
        int lastLeaf = ((size-1)-1)/2;  //找到倒数第一个非叶子节点
        for(int root=lastLeaf;root>=0;root--){    //从该结点开始,依次向下调整直到根节点
            shiftDown(array,root,size);
        }
        //利用堆删除思想排序,从最后一个元素开始与堆顶元素交换,然后对堆顶元素进行向下调整
        int end = size-1;
        while(end>0){
            swap(array,0,end);
            shiftDown(array,0,end);
            end--;
        }
    }
    public static void swap(int[] array,int a,int b){
        int t = array[a];
        array[a] = array[b];
        array[b] = t;
    }

    public static void main(String[] args) {
        int[] array = {2,5,1,3,8,6,9,4,7,0,6};
        heapSort(array);
        for(int i : array){
            System.out.print(i+" ");
        }
    }
}

结果:

4. 特性总结:

时间复杂度:n个元素进行比较,而且太向下调整,调整的深度为完全二叉树的深度,故时间复杂度为:O(NlogN),logN是log以2为底的N

空间复杂度:没有借助辅助空间,O(1)

稳定性:元素发生了有间隔的交换,不稳定

应用场景:求前k个最小或者最大,可以和其他排序结合起来增加效率

4. 交换排序

基本思想就是根据序列中两个记录键值的比较结果来交换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动

4.1 冒泡排序

1. 思想:

依次将序列元素进行比较,若array[i]>array[i+1],交换两个元素的位置,直到最后一个元素,从中可以得出,每躺冒泡只能确定一个元素的位置,若序列有n个元素,则需要进行n-1躺冒泡,因为序列最后一个元素的位置不用确定。

从比较的次数可以看出:第一躺比较的次数为n-1,第二躺的比较次数为n-2.....即每趟冒泡比较的次数在递减,即比较次数是为n-1-i,i为冒泡的趟数。

2. 画图说明:

3. 冒泡排序的优化:

从上图可以看出第10躺冒泡没有进行,因为序列已经有序,即数据元素不在发生交换。

优化:在每趟进行的开始给一个标记isChage=false,如果该躺冒泡发生了元素交换,将isChange=true,在每趟冒泡完进行判断,如果是Change==false,即没有发生交换,说明序列已经有序,即不用在继续冒泡,直接返回即可。

4. 代码展示:

public class BubbleSort {
    public static void bubbleSort(int[] array){
        int size = array.length;
        for(int i = 0;i < size-1;i++){
            boolean isChange = false;         //为了优化冒泡排序给的标记,当元素不发生交换的时候说明已经有序
            for(int j = 0;j < size-1-i;j++){
                if(array[j+1] < array[j]){
                    swap(array,j,j+1);
                    isChange = true;
                }
            }
            if(isChange == false){     //如果元素不发生交换,直接返回
                return;
            }
        }
    }
    public static void swap(int[] array,int a,int b){
        int t = array[a];
        array[a] = array[b];
        array[b] = t;
    }

    public static void main(String[] args) {
        int[] array = {2,5,1,3,8,6,9,4,7,0,6};
        bubbleSort(array);
        for(int i : array){
            System.out.print(i+" ");
        }
    }
}

结果:

5. 特性总结:

时间复杂度:冒泡的趟数,每趟的比较次数,O(N^2)

空间复杂度:不借助辅助空间,O(1)

稳定性:数据元素虽然发生了交换,但是没有间隔交换,稳定

4.2 快速排序

4.2.1. 思想

快速排序是Hoare提出的一种二叉树结构的交换排序方法。

基本思想为:任取待排元素序列中的某个元素作为基准值(这里我们取最右侧元素为基准值),按照该基准值将序列划分为两个区间,左侧比基准值小,右侧比基准值大,再分别用快速排序递归排左区间和右区间。

参考代码:

public static void quickSort(int[] array,int left,int right){   //左闭右开
        if(right-left > 1){       //递归的返回条件,区间最少得有两个元素
            int div = partition(array,left,right);
            quickSort(array,left,div);    //递归排左侧
            quickSort(array,div+1,right);   //递归排右侧
        }
    }

故只要实现分割方法即可。

4.2.2 三种分割方式

1. Hoare法

思想:在左边找比基准值大的,右边找比基准值小的,两个交换位置,最后将较大一侧的第一个元素与基准值交换位置。

画图说明:

参考代码:

 //分割区间方法1:hoare:左边找比基准值大的,右边找比基准值小的,两个交换位置,最后再将基准值放到中间的位置
    public static int partition1(int[] array,int left,int right){
        int key = array[right-1];   //找基准值,以最右侧元素为基准值
        int begin = left;    //在左侧找的下标
        int end = right-1;    //在右侧找的下标
        while(begin < end){
            while(array[begin] <= key && begin < end){  //左侧找大的,不能越界
                begin++;
            }
            while(array[end] >= key && end > begin){    //右侧找小的,不能越界
                end--;
            }
            if(begin != end){
                swap(array,begin,end);    //begin与end不在同一位置的时候交换,否则没有交换的必要
            }
        }
        if(begin != right-1){
            swap(array,begin,right-1);    //将基准值与begin位置的元素交换,begin或者end都行
        }
        return end;        //将分割的位置返回,begin与end都可以
    }

2. 挖坑法

思想:将基准值存入key中,基准值的位置为第一个坑位,在左侧找比基准值大的,放到第一个坑位上,此时这个元素的原始位置又形成了一个新的坑位,再从右侧找比基准值小的,放到前面的坑位上,依次循环,即将序列分割为两部分。

画图说明:

参考代码:

 //分割区间方法二:挖坑法:基准值是一个坑位,左侧找大的放到基准值的坑位上,此时形成了新的坑位,再在右侧找小的放到上一个坑位,依次循环
    public static int partition2(int[] array,int left,int right){
        int key = array[right-1];  //取最右侧元素为基准值,end的位置形成了第一个坑位
        int begin = left;
        int end = right-1;
        while(begin < end){
            while(begin < end && key >= array[begin]){   //在左侧找比基准值大的
                begin++;
            }
            if(begin < end){
                array[end] = array[begin];   //填end坑位,重新生成begin坑位
            }
            while(begin < end && key <= array[end]){    //在右侧找比基准值小的
                end--;
            }
            if(begin < end){
                array[begin] = array[end];    //填begin坑位,重新生成end坑位
            }
        }
        array[begin] = key;     //将基准值填充在最后一个坑位
        return end;
    }

3. 前后标记法

思想:给两个标记cur,pre,pre标记cur的前一个,cur开始标记第一个元素,依次往后走,cur小于区间的右边界,如果cur小于基准值并且++pre不等于cur交换cur与pre位置的元素,最后交换++pre与基准值位置的元素。

画图说明:

参考代码:

  //分割区间方法三:前后标记法
    public static int partition3(int[] array,int left,int right){
        int key = array[right-1];
        int cur = left;
        int pre = cur-1;
        while(cur < right){
            if(array[cur] < key && ++pre != cur){   //当cur位置的元素小于基准值并且++pre!=cur的时候,交换
                swap(array,cur,pre);
            }
            cur++;
        }
        if(++pre != right-1){        //++pre为与基准值交换的位置,所以当++pre!=right-1的时候,交换基准值的位置
            swap(array,pre,right-1);
        }
        return pre;
    }

4.2.3 快速排序的优化

快速排序的优化:对基准值的选取进行优化,这样做是为了选取的基准值尽可能的将区间的左右侧分的均匀一点儿。

优化方法:三数取中法取基准值,三数:区间的中间元素,最左侧元素,最右侧元素,取它们三个的中间值。

参考代码:

//快排优化:三数取中法来取基准值,左侧,右侧,中间这三个数的中间值来作为基准值,这里返回的是基准值下标
    public static int getIndexOfMid(int[] array,int left,int right){
        int mid = left+((right-left)>>1);
        if(array[left] < array[right-1]){    //最右侧的下标为right-1
            if(array[mid] < array[left]){
                return left;
            }else if(array[mid] > array[right-1]){
                return right-1;
            }else{
                return mid;
            }
        }else{
            if(array[mid] < array[right-1]){
                return right-1;
            }else if(array[mid] > array[left]){
                return left;
            }else{
                return mid;
            }
        }
    }

具体与之前代码结合方式,我这里选取一种分割方法来进行优化:

参考代码:

//分割区间方法三:前后标记法
    public static int partition3(int[] array,int left,int right){
        int index = getIndexOfMid(array,left,right);   //用三数取中法获得基准值的下标
        if(index != right-1){
            swap(array,index,right-1);    //如果下表不在最右侧就交换
        }
        int key = array[right-1];
        int cur = left;
        int pre = cur-1;
        while(cur < right){
            if(array[cur] < key && ++pre != cur){   //当cur位置的元素小于基准值并且++pre!=cur的时候,交换
                swap(array,cur,pre);
            }
            cur++;
        }
        if(++pre != right-1){        //++pre为与基准值交换的位置,所以当++pre!=right-1的时候,交换基准值的位置
            swap(array,pre,right-1);
        }
        return pre;
    }

4.2.4 快速排序的非递归方式

非递归的快速排序借助栈这一数据结构

参考代码:

 //非递归的快速排序,利用栈来保存分割的区间,传参只需要传数组即可
    public static void quickSort(int[] array){
        Stack<Integer> s = new Stack<>();
        s.push(array.length);
        s.push(0);
        while(!s.empty()){
            int left = s.pop();
            int right = s.pop();
            if(right - left == 0){
                continue;
            }
            int div = partition(array,left,right);
            s.push(right);
            s.push(div+1);
            s.push(div);
            s.push(left);
        }
    }

4.2.5 快速排序的特性总结

时间复杂度:有比较,递归,O(NlogN)

空间复杂度:存在递归,递归的深度为完全二叉树的深度,O(logN)

稳定性:数据元素发生有间隔的交换,不稳定

应用场景:数据凌乱且随机

5. 归并排序

1. 思想:

归并排序是将两个有序序列进行合并,但是我们拿到是一个数组,所以得先将数组递归均分为两部分,再将两部分进行合并。

2. 画图说明:

递归均分:

从下往上合并:

3. 代码展示:

public class MergeSort {
    public static void mergeSort(int[] array,int left,int right,int[] temp){
        if(right - left > 1){
            int mid = left+((right-left)>>1);
            mergeSort(array,left,mid,temp);      //递归均分左侧
            mergeSort(array,mid,right,temp);      //递归均分右侧
            mergeData(array,left,mid,right,temp);  //合并两个序列,[left,mid) , [mid,right)
            System.arraycopy(temp,left,array,left,right-left); //拷贝到原数组,源,起始位置,新,起始位置,长度
        }
    }
    public static void mergeData(int[] array,int left,int mid,int right,int[] temp){
        //[begin1,end1),[begin2,end2),为两个合并的区间
        int begin1 = left;
        int end1 = mid;
        int begin2 = mid;
        int end2 = right;
        int index = left;   //辅助数组的下标
        while(begin1 < end1 && begin2 < end2){
            if(array[begin1] <= array[begin2]){
                temp[index++] = array[begin1++];
            }else{
                temp[index++] = array[begin2++];
            }
        }
        while(begin1 < end1){
            temp[index++] = array[begin1++];
        }
        while(begin2 < end2){
            temp[index++] = array[begin2++];
        }
    }
    //重新包装一下,便于用户传参
    public static void mergeSort(int[] array){
        int[] temp = new int[array.length];
        mergeSort(array,0,array.length,temp);
    }
}

4. 非递归的归并排序

给一个间隔,用间隔来表示区间

参考代码:

 //非递归的归并排序
    public static void mergeSortNor(int[] array){
        int size = array.length;
        int[] temp = new int[size];
        int gap = 1;       //先每两个元素归并
        while(gap < size){
            for(int i = 0;i < size;i+=gap*2){
                int left = i;
                int mid = i+gap;
                int right = mid+gap;
                if(mid > size){    //防止mid越界
                    mid = size;
                }
                if(right > size){   //防止right越界
                    right = size;
                }
                mergeData(array,left,mid,right,temp);
            }
            System.arraycopy(temp,0,array,0,size);
            gap <<= 1;
        }
    }

5. 特性总结:

时间复杂度:O(NlogN)

空间复杂度:借助了辅助空间,为辅助数组的大小,O(N)

稳定性:数据元素不发生有间隔的交换,稳定

应用场景:适合外部排序

6. 计数排序(非比较类型的排序)

1. 思想:

计数排序又称鸽巢原理,是对哈希直接定址法的变形应用

步骤:

统计相同元素出现次数

根据统计的结果将序列回收到原来的序列中

2. 画图说明:

3. 代码展示:

public class CountSort {
    public static void countSort(int[] array){
        //找出数组的最大值与最小值
        int maxNum = array[0];
        int minNum = array[0];
        for(int i = 1;i < array.length;i++){
            if(array[i] > maxNum){
                maxNum = array[i];
            }
            if(array[i] < minNum){
                minNum = array[i];
            }
        }
        int range = maxNum - minNum + 1;   //序列元素的范围大小
        int[] count = new int[range];      //new一个范围大小的数组
        for(int i = 0;i < array.length;i++){
            count[array[i]-minNum]++;      //读取
        }
        int index = 0;     //存入原数组的下标
        for(int i = 0;i < range;i++){
            while(count[i] > 0){
                array[index] = i + minNum;
                index++;
                count[i]--;
            }
        }
    }

}

4. 性能总结:

时间复杂度:O(N)

空间复杂度:O(M),M为数据范围的大小

稳定性:数据元素没有进行有间隔的交换,稳定

应用场景:数据元素集中在某个范围

7. 排序算法总结

排序方法 最好 平均 最坏 空间复杂度 稳定性
插入排序 O(n) O(n^2) O(n^2) O(1) 稳定
希尔排序 O(n) O(n^1.3) O(n^2) O(1) 不稳定
选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
堆排序 O(n*log(n)) O(n*log(n)) O(n*log(n)) O(1) 不稳定
冒泡排序 O(n) O(n^2) O(n^2) O(1) 稳定
快速排序 O(n*log(n)) O(n*log(n)) O(n^2) O(log(n)) 不稳定
归并排序 O(n*log(n)) O(n*log(n)) O(n*log(n)) O(n) 稳定

以上就是Java实现基本排序算法的示例代码的详细内容,更多关于Java排序算法的资料请关注我们其它相关文章!

(0)

相关推荐

  • java 中基本算法之希尔排序的实例详解

    java 中基本算法之希尔排序的实例详解 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shell于1959年提出而得名. 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序:随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止. 基本思想:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差

  • java 数据结构基本算法希尔排序

    C语言数据结构基本算法希尔排序 前言: 基本思想:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序, 然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序.当增量减到1时,进行直接插入排序后,排序完成. 实现代码: public class ShellSort { /** * 原理:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的 * 下标相差d.对每组

  • Java深入了解数据结构中常见的排序算法

    目录 一,概念 1,排序 2,稳定性 二,排序详解 1,插入排序 ①直接插入排序 2,选择排序 ①直接选择排序 ②堆排序 3,交换排序 ①冒泡排序 ②快速排序 4,归并排序 一,概念 1,排序 排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作. 平时的上下文中,如果提到排序,通常指的是排升序(非降序). 通常意义上的排序,都是指的原地排序(in place sort). 2,稳定性 两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算

  • java 基本算法之归并排序实例代码

    java 基本算法之归并排序实例代码 原理:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表, * 即把待排序序列分为若干个子序列,每个子序列是有序的.      * 然后再把有序子序列合并为整体有序序列. 实例代码: public class MergeSort { /** * * * * @param args */ public static void main(String[] args) { int a[] = { 49, 38, 65, 97, 76, 13,

  • Java数据结构之基于比较的排序算法基本原理及具体实现

    目录 1. 七大基于比较的排序-总览 1.1常见基于比较的排序分类 1.2时间复杂度,空间复杂度以及稳定性. 2.直接插入排序 2.1 直接插入排序的基本思想 2.2 直接插入排序动画演示 2.3 代码示例 2.4 时间复杂度,空间复杂度以及稳定性 3. 希尔排序 3.1 算法思想 3.2 图片演示 3.3 代码示例 3.4 时间复杂度,空间复杂度以及稳定性 4.选择排序 4.1 算法思想 4.2 动画演示 4.3 代码示例 4.4 时间复杂度,空间复杂度以及稳定性 5.堆排序 5.1 算法思想

  • java中几种常见的排序算法总结

    目录 本节目标: [插入排序] [优化版] [希尔排序] [选择排序] [堆排序]  [冒泡排序] 介绍一个冒泡排序的优化方法:  [快速排序] [归并排序] [正文] [代码简介:]  [排序总结] 本节目标: :分析常见的比较排序算法基本原理及实现 :分析排序算法的性能分析 :分析Java中常用排序方法 1 排序 排序,就是使一串记录,按照其中某个或某些关键字的大小,递增或递减排列的操作. 平时的上下文中,提到排序 通常指排升序. 2 稳定性 两个相同的数据,如果经过排序后,排序算法能保证其

  • Java常用的八种排序算法及代码实现+图解

    目录 1.冒泡排序 冒泡排序法的思路 2.冒泡排序法的代码实现 3.冒泡排序法优化 4.选择排序 5.插入排序 插入排序的思路 经典的排序算法有八种,分别为: 冒泡排序 选择排序 插入排序 归并排序 希尔排序 快速排序 堆排序 基数排序 其中冒泡排序.选择排序.插入排序称为三大基本排序. 虽然这三大基本排序算法时间复杂度都是O(n2),但是其实细细讨论之下,还是有各自的特点的. 1.冒泡排序 冒泡排序法的思路 基本思路: 假设我们需要进行升序排列 进行N轮的比较,每一轮将相邻的两个元素依次比较,

  • Java实现基本排序算法的示例代码

    目录 1. 概述 2. 插入排序 2.1 直接插入排序 2.2 希尔排序(缩小增量排序) 3. 选择排序 3.1 直接选择排序 3.2 堆排序 4. 交换排序 4.1 冒泡排序 4.2 快速排序 5. 归并排序 6. 计数排序(非比较类型的排序) 7. 排序算法总结 1. 概述 排序概念:就是将一串记录按照其中某个或某些关键字的大小,递增或递减的排列起来的操作. 稳定性:通俗的将就是数据元素不发生有间隔的交换,例如: 内部排序:数据元素全部放在内存中的排序 外部排序:数据元素太多不能一次加载到内

  • Java实现拓扑排序算法的示例代码

    目录 拓扑排序原理 1.点睛 2.拓扑排序 3.算法步骤 4.图解 拓扑排序算法实现 1.拓扑图 2.实现代码 3.测试 拓扑排序原理 1.点睛 一个无环的有向图被称为有向无环图.有向无环图是描述一个工程.计划.生产.系统等流程的有效工具.一个大工程可分为若干子工程(活动),活动之间通常有一定的约束,例如先做什么活动,有什么活动完成后才可以开始下一个活动. 用节点表示活动,用弧表示活动之间的优先关系的有向图,被称为 AOV 网. 在 AOV 网中,若从节点 i 到节点 j 存在一条有向路径,则称

  • Java语言字典序排序算法解析及代码示例

    字典序法就是按照字典排序的思想逐一产生所有排列. 在数学中,字典或词典顺序(也称为词汇顺序,字典顺序,字母顺序或词典顺序)是基于字母顺序排列的单词按字母顺序排列的方法. 这种泛化主要在于定义有序完全有序集合(通常称为字母表)的元素的序列(通常称为计算机科学中的单词)的总顺序. 对于数字1.2.3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的.例如对于5个数字的排列 12354和12345,排列12345在前,排列12354在后.按照这样的规定,5个数字的所有的

  • Java实现8种排序算法的示例代码

    冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次数,也是冒泡的结果位置下标,5个数组循环5次 for (int i = 0; i < a.length; i++) { //从最后向前面两两对比,j是比较中下标大的值 for (int j = a.length - 1; j > i; j--) { //让小的数字排在前面 if (a[j] <

  • Java实现常见的排序算法的示例代码

    目录 一.优化后的冒泡排序 二.选择排序 三.插入排序 四.希尔排序 五.快速排序 六.随机化快速排序 七.归并排序 八.可处理负数的基数排序 一.优化后的冒泡排序 package com.yzh.sort; /* 冒泡排序 */ @SuppressWarnings({"all"}) public class BubbleSort { public static void BubbleSort(int[]a){ for (int i = 0; i <a.length-1 ; i+

  • Java实现折半插入排序算法的示例代码

    目录 排序算法介绍 折半插入排序 原理 代码实现 复杂度分析 算法实践 排序算法介绍 排序算法是通过特定的算法因式将一组或多组数据按照既定模式进行重新排序.最终序列按照一定的规律进行呈现. 在排序算法中,稳定性和效率是我们经常要考虑的问题. 稳定性:稳定是指当两个相同的元素同时出现于某个序列之中,则经过一定的排序算法之后,两者在排序前后的相对位置不发生变化. 复杂度分析: (1)时间复杂度:即从序列的初始状态到经过排序算法的变换移位等操作变到最终排序好的结果状态的过程所花费的时间度量. (2)空

  • python实现经典排序算法的示例代码

    以下排序算法最终结果都默认为升序排列,实现简单,没有考虑特殊情况,实现仅表达了算法的基本思想. 冒泡排序 内层循环中相邻的元素被依次比较,内层循环第一次结束后会将最大的元素移到序列最右边,第二次结束后会将次大的元素移到最大元素的左边,每次内层循环结束都会将一个元素排好序. def bubble_sort(arr): length = len(arr) for i in range(length): for j in range(length - i - 1): if arr[j] > arr[j

  • Golang实现常见排序算法的示例代码

    目录 前言 五种基础排序算法对比 1.冒泡排序 2.选择排序 3.插入排序 4.快速排序 前言 现在的面试真的是越来越卷了,算法已经成为了面试过程中必不可少的一个环节,你如果想进稍微好一点的公司,「算法是必不可少的一个环节」.那么如何学习算法呢?很多同学的第一反应肯定是去letcode上刷题,首先我并不反对刷题的方式,但是对于一个没有专门学习过算法的同学来说,刷题大部分是没什么思路的,花一个多小时暴力破解一道题意义也不大,事后看看别人比较好的解法大概率也记不住,所以我觉得「专门针对算法进行一些简

  • PHP实现常见排序算法的示例代码

    目录 1.冒泡排序 2.选择排序 3.快速排序 4.插入排序 补充 1.冒泡排序 两两相比,每循环一轮就不用再比较最后一个元素了,因为最后一个元素已经是最大或者最小. function maopaoSort ($list) { $len = count($list); for ($i = 0; $i < $len - 1; $i++) { for ($j = 0; $j < $len - $i - 1; $j++) { if ($list[$j] > $list[$j + 1]) { $

  • C语言实现经典排序算法的示例代码

    目录 一.冒泡排序 1.原理 2.实现 3.算法分析 二.选择排序 1.原理 2.实现 3.算法分析 三.插入排序 1.原理 2.实现 3.算法分析 四.希尔排序 1.原理 2.实现 3.算法分析 总结 一.冒泡排序 1.原理 从数组的头开始不断比较相邻两个数的大小,不断将较大的数右移,一个循环后,最大数移至最后一位,无序数组规模减一.不断重复前面动作,知道数组完全有序. 2.实现 void swap(int* a, int* b) { int temp = *a; *a = *b; *b =

随机推荐