最通俗易懂的排序算法(二)

本文深入讲解了简单选择排序、堆排序、归并排序和基数排序等经典排序算法,包括各自的原理、步骤及代码实现,旨在帮助读者理解不同排序算法的特点和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单选择排序 堆排序 归并排序 基数排序

一、选择排序

  选择排序的基本思想是每一趟从待排序的元素中选出关键字最小的元素,顺序放在已排好序的子表的最后,直到全部元素排序完毕。这种排序方法每一趟总是从无序区中选出全局最小(或最大)的关键字,所以适合从大量的元素中选择一部分排序元素

1.简单选择排序
  从待排序序列中选出最小的元素,将它与无序区中第一个元素交换,往复循环(每趟选出一个无序区中的最小元素),直到序列中最大的元素归位。   一趟简单选择排序过程:先假设待排序序列中第一(i)个元素为最小元素,它的下标记为最小下标minIndex,然后从第二(i+1)个元素开始依次与最小下标对应元素比较,如果第二(i+1)个元素小于最小下标元素,则最小下标为第二(i+1)个元素下标,依次循环直到序列中最后一个元素,最后将最小下标minIndex对应的元素与第(i)个元素交换。
选择排序代码:

import java.util.Arrays;
public class SelectSort{
    public static void main(String[] args){
        int[] array = new int[] {9,8,7,6,5,4,3,2,1,0};
        selectSort(array);
        System.out.println(Arrays.toString(array));
    }
    public static void selectSort(int[] array){
        for(int i=0;i<array.length-1;i++){
            int minIndex = i;
        	for(int j=i+1;j<array.length;j++){
            	if(array[j]<array[minIndex]){
                	minIndex=j;
                }
            }
            if(i!=minIndex){
            	int temp = array[i];
                array[i] = arrau[minIndex];
                array[minIndex] = temp;
            }
        }
    }
}

2.堆排序

二、归并排序

  归并排序是多次将两个或两个以上的有序表合并成一个新的有序表。
算法过程分析:
  将待排序数组R分为两个数组,即R[low ... mid]、R[mid+1 ... high],使这两个子数组有序,然后将这两个数组合并到临时数组R1中,最后将R1复制到R。为了使两个子数组有序,通过递归将子数组一直分割,直到数组的大小为1,此时因为数值中只有一个元素,所以数组是有序的。之后将这些数组依次合并,直到所有小的数组合并在一起。

算法图解:
在这里插入图片描述归并排序算法:

import java.util.Arrays;

/**
 * merge sort 归并排序
 */
public class MergeSort {
    public static void main(String[] args) {
        int[] array = new int[]{1,0,2,9,8,3,5,4,7,6};
        mergeSort(array,0,array.length-1);
        System.out.println(Arrays.toString(array));
    }

    //归并排序
    public static void mergeSort(int[] array,int low,int high){
        //递归的出口
        if (low<high){
            int mid = (low+high)/2;
            //处理左边
            mergeSort(array, low, mid);
            //处理右边
            mergeSort(array, mid+1, high);
            //归并
            merge(array,low,mid,high);
        }
    }
    //两个数组的归并排序为一个数组
    public static void merge(int[] array,int low,int mid,int high){
        //用于存储归并后的临时数组
        int[] temp = new int[high-low+1];
        //记录第一个数组中需要遍历的下标
        int i = low;
        //记录第二个数组中需要遍历的下标
        int j = mid+1;
        //临时数组的下标
        int index = 0;
        //遍历两个数组取出小的数字,放入临时数组中
        while(i<=mid&&j<=high){
            if(array[i]<array[j]){
                //把小的数放到临时数组中,下标加1
                temp[index++]=array[i++];
            }else{
                temp[index++]=array[j++];
            }
        }
        //当一个数组为空时,处理另一数组中剩下的数
        while(i<=mid){
            temp[index++]=array[i++];
        }
        while(j<=high){
            temp[index++]=array[j++];
        }
        //将临时数组中的数据重新存入原数组中
        for (int k = 0; k < temp.length; k++) {
            array[low+k]=temp[k];
        }
    }

}
三、基数排序

  前面的几种排序都是通过基于关键字之间的比较来实现的,而基数排序不需要进行关键字之间的比较。基数排序的基本思想是(最低位优先)先按最低位对元素进行排序,在此基础上再按照百位进行排序,依次类推,由低位向最高位,每一趟都是根据关键字的一位在前一趟的基础上对所有元素排序,直到最高位,就完成了排序。
算法图解:
在这里插入图片描述基数排序算法:

import java.util.Arrays;

/**
 * radix sort 基数排序
 */
public class RadixSort {
    public static void main(String[] args) {
        int[] array = new int[]{23,16,189,64,7,286,56,1,689,44};
        radixSort(array);
        System.out.println(Arrays.toString(array));
    }
    //基数排序方法
    public static void radixSort(int[] array){
        //存储数组中最大的数字
        int max = array[0];
        for (int i = 0; i < array.length; i++) {
            if (array[i]>max){
                max=array[i];
            }
        }
        //计算最大值是几位数
        int length = (max+"").length();
        //用于临时存储数据的数组
        int[][] temp = new int[10][array.length];
        //记录每个“桶”中数据的个数
        int[] counts = new int[10];
        //根据数组中元素的最大长度决定比较的次数
        for (int i = 0,n = 1; i < length; i++, n*=10) {
            //对数组中每个元素计算余数
            for (int j = 0; j < array.length; j++) {
                int ys = array[j]/n%10;
                //将当前遍历的数据放在临时数组的指定位置
                temp[ys][counts[ys]]=array[j];
                //放入一个数数量加1
                counts[ys]++;
            }
            //将临时数组中的数字取出来
            int index = 0;
            for (int k = 0; k < counts.length; k++) {
                if(counts[k]!=0){
                    for (int l = 0; l < counts[k]; l++) {
                        //取出临时数组中的数到原数组中
                        array[index]=temp[k][l];
                        index++;
                    }
                    //取出数据后将相应桶中的数据个数置0
                    counts[k]=0;
                }

            }
        }
    }
}

基数排序的队列实现:

import java.util.Arrays;

/**
 * radix sort 基数排序
 */
//队列
class MyQueue {
    int[] queue;
    public MyQueue(){
        queue = new int[0];
    }

    //入队操作
    public void add(int number){
        int[] newQueue = new int[queue.length+1];
        for (int i = 0;i<queue.length;i++){
            newQueue[i]=queue[i];
        }
        newQueue[newQueue.length-1]=number;
        queue = newQueue;
    }
    //出队操作
    public int poll(){
        int number = queue[0];
        int[] newQueue = new int[queue.length-1];
        for (int i=0;i<newQueue.length;i++){
            newQueue[i]=queue[i+1];
        }
        queue = newQueue;
        return number;
    }
    //判断队列是否为空
    public boolean isEmpty(){
        return queue.length==0;
    }
}

public class RadixSort {
    public static void main(String[] args) {
        int[] array = new int[]{23,16,189,64,7,286,56,1,689,44};
        radixSort(array);
        System.out.println(Arrays.toString(array));
    }
    public static void radixSort(int[] array){
    	//找出待排序数组中的最大元素
        int max = arrray[0];
        for(int i= 0; i < array.length; i++){
        	if(array[i] > max)
            	max = array[i];
        }
        //最大元素的位数,转换成String类型
        int length = (max+"").length();
        //临时存储数据的队列数组;队列数组赋值
        MyQueue[] temp = new MyQueue[10];
        for(int i = 0; i < temp.length; i++){
        	temp[i] = new MyQueue();
        }
        //根据最大元素的位数进行决定比较次数
        for(int i = 0,n = 1; i < length; i++, n*=10){
        	//对数组中,每个元素计算余数ys
            for(int j = 0;j < array.length; j++){
            	int ys = array[j]/n%10;
                //将当前数据存在指定队列中
                temp[ys].add(array[j]);
            }
            //将临时队列中的数据取出到原数组中
            int index = 0;
            //把所有队列中的数据都取出来
            for(int k = 0; k < temp.length; k++){
            	while(!temp[k].isEmpty()){
                    //取出元素
                	array[index] = temp[k].poll();
                    //记录下一个位置
                    index++;
                }
            }
        }
    }
}

使用集合实现基数排序:

import java.util.ArrayList;
import java.util.Arrays;


/**
 * 使用集合实现基数排序
 */
public class RadixListSort {
    public static void main(String[] args) {
        int[] array = new int[]{23,16,189,64,7,286,56,1,689,44};
        radixSort(array);
        System.out.println(Arrays.toString(array));
    }
    public static void radixSort(int[] array){
        //找出待排序数组中的最大元素
        int max = array[0];
        for(int i= 0; i < array.length; i++){
            if(array[i] > max)
                max = array[i];
        }
        //最大元素的位数,转换成String类型
        int length = (max+"").length();
        //临时存储数据的队列数组;集合数组赋值
        ArrayList<ArrayList<Integer>> temp= new ArrayList<>();
        for(int i = 0; i < 10; i++){
            temp.add(new ArrayList<Integer>(10));
        }


        //根据最大元素的位数进行决定比较次数
        for(int i = 0,n = 1; i < length; i++, n*=10){
            //对数组中,每个元素计算余数ys
            for(int j = 0;j < array.length; j++){
                int ys = array[j]/n%10;
                //将当前数据存在指定集合中
                temp.get(ys).add(array[j]);
            }
            //将临时集合中的数据取出到原数组中
            int index = 0;
            for(int k = 0;k < 10; k++){
                for (Integer t:temp.get(k)) {
                    array[index]=t;
                    index++;
                }
//                for (int m = 0; m < temp.get(k).size(); m++) {
//                    int c = (int)temp.get(k).get(m);
//                    array[index++]=c;
//                }
                //清空集合
                temp.get(k).clear();
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值