排序【数据结构与算法Java】

简介: 排序【数据结构与算法Java】

排序

插入类排序

直接插入排序

折半插入排序

希尔排序

package sort1;
/**
 * @author CSDN@日星月云
 * @date 2022/10/30 21:29
 */
public class InsertSort1 {
    public static void main(String[] args) {
        int[]nums={-1,1,2,3,4,5,0,9,8,7,6};//0号不存储有效数字
        //直接插入排序 稳定
//        new InsertSort1().insertSort(nums);
        //改进的直接插入排序 稳定
//        new InsertSort1().insertSortPlus(nums);
        //折半插入排序 稳定
//        new InsertSort1().biInsertSort(nums);
        //增量序列 不稳定
//        new InsertSort1().shellSort(nums,new int[]{4,2,1});
        new InsertSort1().shellSort(nums,new int[]{7,3,1});
        for (int i = 1; i < nums.length; i++) {
            System.out.print(nums[i]+"\t");
        }
    }
    //直接插入排序
    void insertSort(int[] nums){
        for (int i = 2; i <nums.length ; i++) {
            nums[0]=nums[i];//监视哨备份待查记录
            int j;
            for (j = i-1; nums[0]<nums[j]; j--) {
                nums[j+1]=nums[j];//记录后移
            }
            nums[j+1]=nums[0];//插入正确位置
        }
    }
    //待插记录已是当前有序的最大记录,不需要后移排序
    //改进的直接插入排序
    void insertSortPlus(int[] nums){
        for (int i = 2; i <nums.length ; i++) {
            if(nums[i]<nums[i-1]){//如果不小于,就是待插记录已是当前有序的最大记录
                nums[0]=nums[i];//监视哨备份待查记录
                int j;
                for (j = i-1; nums[0]<nums[j]; j--) {
                    nums[j+1]=nums[j];//记录后移
                }
                nums[j+1]=nums[0];//插入正确位置
            }
        }
    }
    //折半插入排序
    //因为插入到有序列中,有折半快速找到位置
    void biInsertSort(int []nums){
        for (int i = 2; i <nums.length ; i++) {
            if(nums[i]<nums[i-1]){//如果不小于,就是待插记录已是当前有序的最大记录
                nums[0]=nums[i];//监视哨备份待查记录
                //折半查找nums[i]插入位置
                int low=1;
                int high=i-1;
                while (low<high){
                    int mid=(low+high)/2;
                    if(nums[0]<nums[mid]){
                        high=mid-1;
                    }else{
                        low=mid+1;
                    }
                }
                for (int j = i-1; j>=low; j--) {
                    nums[j+1]=nums[j];//记录后移
                }
                nums[low]=nums[0];//插入正确位置
            }
        }
    }
    //希尔排序
    //最小增量排序
    void shellInsert(int[] nums,int dk){
        for (int i = dk+1; i <nums.length ; i++) {
            if(nums[i]<nums[i-1]){//如果不小于,就是待插记录已是当前有序的最大记录
                nums[0]=nums[i];//监视哨备份待查记录
                int j;
                for (j = i-dk; j>0&&nums[0]<nums[j]; j-=dk) {
                    nums[j+dk]=nums[j];//记录后移
                }
                nums[j+dk]=nums[0];//插入正确位置
            }
        }
    }
    //dlta 增量序列
    void shellSort(int[] nums,int dlta[]){
        int t=dlta.length;//t为增量序列的长度
        for (int k=0;k<t;k++){
            shellInsert(nums,dlta[k]);
        }
    }
}

交换类排序

冒泡排序

package sort;
/**
 * @author CSDN@日星月云
 * @date 2022/10/30 22:06
 */
public class SwapSort {
    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 4, 5, 0, 9, 8, 7, 6};//0号不存储有效数字
        //冒泡排序
//        new SwapSort1().bubbleSort(nums);
        //改进冒泡排序
        new SwapSort().bubbleSortPlus(nums);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + "\t");
        }
    }
    public void swap(int [] nums,int i,int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }
    //冒泡排序
    public void bubbleSort(int[] nums){
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j <nums.length-1-i ; j++) {
                if(nums[j]>nums[j+1]){
                    swap(nums,j,j+1);
                }
            }
        }
    }
    //改进冒泡排序
    //如已排好序,直接跳出
    public void bubbleSortPlus(int[] nums){
        boolean flag=true;
        for (int i = 0; i < nums.length&&flag; i++) {
            flag=false;
            for (int j = 0; j <nums.length-1-i ; j++) {
                if(nums[j]>nums[j+1]){
                    swap(nums,j,j+1);
                    flag=true;
                }
            }
        }
    }
}

快速排序

package sort1;
/**
 * @author CSDN@日星月云
 * @date 2022/10/21 23:13
 */
public class QuickSort1 {
    public static void main(String[] args) {
        int[]nums={-1,1,2,3,4,5,0,9,8,7,6};//0号不存储有效数字
        new QuickSort1().qkSort(nums,1, nums.length-1);
        for (int i = 1; i < nums.length; i++) {
            System.out.print(nums[i]+"\t");
        }
    }
    void qkSort(int[]nums,int low,int high){
        int pos;
        if (low<high){
            pos=qkPass(nums, low,high);
            qkSort(nums, low,pos-1);
            qkSort(nums, pos+1,high);
        }
    }
    int qkPass(int[] nums,int low,int high){
        nums[0]=nums[low];//枢轴
        while(low<high){
            while (low<high&&nums[high]>nums[0]) --high;
            nums[low]=nums[high];
            while (low<high&&nums[low]<nums[0]) ++low;
            nums[high]=nums[low];
        }
        nums[low]=nums[0];
        return low;
    }
}
package sort;
/**
 * @author CSDN@日星月云
 * @date 2022/10/21 23:13
 */
public class QuickSort {
    public static void main(String[] args) {
        int[]nums={1,2,3,4,5,0,9,8,7,6};//0号存储有效数字
        new QuickSort().qkSort(nums,0, nums.length-1);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+"\t");
        }
    }
    void qkSort(int[]nums,int low,int high){
        int pos;
        if (low<high){
            pos=qkPass(nums, low,high);
            qkSort(nums, low,pos-1);
            qkSort(nums, pos+1,high);
        }
    }
    int qkPass(int[] nums,int low,int high){
        int tmp=nums[low];//枢轴
        while(low<high){
            while (low<high&&nums[high]>tmp) --high;
            nums[low]=nums[high];
            while (low<high&&nums[low]<tmp) ++low;
            nums[high]=nums[low];
        }
        nums[low]=tmp;
        return low;
    }
}

选择类排序

简单选择排序

package sort;
/**
 * @author CSDN@日星月云
 * @date 2022/10/30 22:14
 */
public class SelectSort {
    public static void main(String[] args) {
        int[]nums={1,2,3,4,5,0,9,8,7,6};
        //简单选择排序 不稳定
        //树形选择排序
        //堆排序 不稳定
        new SelectSort().selectSort(nums);
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+"\t");
        }
    }
    public void swap(int [] nums,int i,int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }
    //简单选择排序
    void selectSort(int[] nums){
        for (int i = 0; i < nums.length; i++) {
            int k=i;
            for (int j = i+1; j <nums.length ; j++) {
                if (nums[j]<nums[k]){//k是擂台
                    k=j;
                }
            }
            if (k!=i){
                swap(nums,i,k);
            }
        }
    }
}

树形选择排序

堆排序

package sort1;
import sort.InsertSort;
/**
 * @author CSDN@日星月云
 * @date 2022/10/30 23:04
 */
public class HeapSort1 {
    public static void main(String[] args) {
        int max=Integer.MAX_VALUE;
//        //测试堆的筛选
//        int[]nums={max,72,12,19,33,68,33,80,46};//0号不存储有效数字
//        new HeapSort1().heapAdjust(nums,1, nums.length-1);
        //测试建立初始堆
        int[]nums={max,46,12,33,72,68,19,80,33};//0号不存储有效数字
//        new HeapSort1().createHeap(nums);
        //测试堆排序
        new HeapSort1().heapSort(nums);
        for (int i = 1; i < nums.length; i++) {
            System.out.print(nums[i]+"\t");
        }
        //80  72  68  46  33  33  19  12
    }
    //堆的筛选
    void heapAdjust(int[] nums,int s,int m){
        //已知nums[s..m]中记录的关键字除nums[s]之外均满足堆的定义
        //本函数调整nums[s]的关键字,是nums[s..m]成为一个小顶堆
        int t=nums[s];
        for (int j=2*s;j<=m;j*=2){
            //沿key较小的孩子结点向下筛选
            if (j<m&&nums[j]>nums[j+1]){
                j++;//j为key较小的记录的下标
            }
            if(t<=nums[j]){
                break;
            }
            //t应插入位置s
            nums[s]=nums[j];
            s=j;
        }
        nums[s]=t;
    }
    //建立初始堆
    void createHeap(int [] nums){
        int n=nums.length-1;//有效记录个数
        for (int i=n/2;i>=1;i--){
            heapAdjust(nums,i,n);
        }
    }
    //堆排序
    void heapSort(int [] nums){
        int n=nums.length-1;//有效记录个数
        createHeap(nums);
        for (int i=n;i>=2;i--){
            nums[0]=nums[1];
            nums[1]=nums[i];
            nums[i]=nums[0];
            heapAdjust(nums,1,i-1);
        }
    }
}

归并类排序

二路归并排序

自然归并排序

package sort1;
/**
 * @author CSDN@日星月云
 * @date 2022/10/30 22:25
 * 归并类排序
 */
public class MergeSort1 {
    public static void main(String[] args) {
        int[]nums={-1,1,2,3,4,5,0,9,8,7,6};//0号不存储有效数字
        //二路归并排序
//        int[] copy=new int[nums.length];
//        for (int i=0;i<nums.length;i++){
//            copy[i]=nums[i];
//        }
//        new MergeSort1().mergeSort(nums,copy,0,nums.length-1);
        //自然归并排序
        new MergeSort1().natureMergeSort(nums,nums.length);
        for (int i = 1; i < nums.length; i++) {
            System.out.print(nums[i]+"\t");
        }
    }
    //二路归并排序
    void mergeSort(int [] nums,int[] copy,int left,int right){
        //对上下限值分别为left和right的记录序列L进行归并排序
        //其中copy为同类型的记录,由于复制保存原记录序列
        int middle;
        if(left<right){
            middle=(left+right)/2;//找中间位置进行划分
            mergeSort(nums,copy,left,middle);//对左半部分进行递归归并排序
            mergeSort(nums,copy,middle+1,right);//对右半部分进行递归归并排序
            merge(nums,copy,left,right,middle);//进行归并
        }
    }
    void merge(int[] nums,int[] copy,int left,int right,int middle){
        int i,p1,p2;
        for (i=left;i<=right;i++){//用copy记录临时保存待排序记录序列
            copy[i]=nums[i];
        }
        p1=left;//左半部分有序记录的起始位置
        p2=middle+1;//右半部分有序记录的起始位置
        i=left;//左半部分开始进行归并
        while(p1<=middle&&p2<=right){
            //取两个有序半区中关键字较小的记录
            if (copy[p1]<=copy[p2]){
                nums[i]=copy[p1];//去较小的记录放到合并后的记录序列中
                p1++;
            } else{
                nums[i]=copy[p2];
                p2++;
            }
            i++;
        }
        //剩下的序列无论是左半部分还是右半部分都直接复制到合并后的记录序列中
        while (p1<=middle){
            nums[i]=copy[p1];
            i++;
            p1++;
        }
        while (p2<=middle){
            nums[i]=copy[p2];
            i++;
            p2++;
        }
    }
    //自然归并排序
    //将两个有序的子序列nums[low..m]和nums[m+1..high]归并成一个有序的子序列nums[low..high]
    void merge(int[]nums,int l,int m,int r){
        int i=l,j=m+1,p=0,q;
        int [] copy=new int[r-l+1];
        while (i<=m&&j<=r){
            //取两个有序半区中关键字较小的记录
            if(nums[i]<=nums[j]){
                copy[p++]=nums[i++];
            }else {
                copy[p++]=nums[j++];
            }
        }
        //剩下的序列无论是左半部分还是右半部分都直接复制到合并后的记录序列中
        if (i>m){
            for (q = j; q <=r ; q++) {
                copy[p++]=nums[q];
            }
        }else {
            for (q=i;q<=m;q++){
                copy[p++]=nums[q];
            }
        }
        for (p=0,i=l;i<=r;p++,i++){
            nums[i]=copy[p];//归并完成后将结果复制回R[low..high]
        }
    }
    void natureMergeSort(int[] nums,int n){
        int i,sum,low,mid,high;
        while (true){
            i=0;
            sum=1;
            while (i<n-1){
                low=i;
                while (i<n-1&&nums[i]<nums[i+1]){ i++; }
                mid=i++;
                while (i<n-1&&nums[i]<nums[i+1]){ i++; }
                high=i++;
                if (i<=n){
                    merge(nums,low,mid,high);
                    sum++;
                }
            }
            if (sum==1) break;
        }
    }
}

分配类排序

多关键字排序

链式基数排序

外部排序

置换选择排序

多路归并外排序

相关文章
|
6天前
|
存储 算法 安全
探究‘公司禁用 U 盘’背后的哈希表算法与 Java 实现
在数字化办公时代,信息安全至关重要。许多公司采取“禁用U盘”策略,利用哈希表算法高效管理外接设备的接入权限。哈希表通过哈希函数将设备标识映射到数组索引,快速判断U盘是否授权。例如,公司预先将允许的U盘标识存入哈希表,新设备接入时迅速验证,未授权则禁止传输并报警。这有效防止恶意软件和数据泄露,保障企业信息安全。 代码示例展示了如何用Java实现简单的哈希表,模拟公司U盘管控场景。哈希表不仅用于设备管理,还在文件索引、用户权限等多方面助力信息安全防线的构建,为企业数字化进程保驾护航。
|
3月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
109 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
5天前
|
Java 程序员
Java 排序神器:Comparable 和 Comparator 该怎么选?
嗨,大家好,我是小米!今天和大家聊一聊Java社招面试中常考的经典问题——Comparable和Comparator的区别。Comparable定义对象的自然排序,适用于单一固定的排序规则;Comparator则是策略接口,用于定义自定义排序规则,适用于多样化或多变的排序需求。掌握这两者的区别是理解Java排序机制的基础,也是面试中的加分题。结合实际项目场景深入探讨它们的应用,能更好地打动面试官。如果你觉得有帮助,欢迎点赞、收藏、分享,期待你的一键三连!我们下期见~ 我是小米,一个喜欢分享技术的程序员,关注我的微信公众号“软件求生”,获取更多技术干货!
37 20
|
5天前
|
存储 人工智能 算法
【C++数据结构——内排序】二路归并排序(头歌实践教学平台习题)【合集】
本关任务是实现二路归并算法,即将两个有序数组合并为一个有序数组。主要内容包括: - **任务描述**:实现二路归并算法。 - **相关知识**: - 二路归并算法的基本概念。 - 算法步骤:通过比较两个有序数组的元素,依次将较小的元素放入新数组中。 - 代码示例(以 C++ 为例)。 - 时间复杂度为 O(m+n),空间复杂度为 O(m+n)。 - **测试说明**:平台会对你编写的代码进行测试,提供输入和输出示例。 - **通关代码**:提供了完整的 C++ 实现代码。 - **测试结果**:展示代码运行后的排序结果。 开始你的任务吧,祝你成功!
25 10
|
5天前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
33 10
|
5天前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
24 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
163 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
135 8
|
3月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
52 6
|
3月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
48 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。