使用Java实现十大排序算法

冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

/**
 * 冒泡排序
 * @ClassName: BubbleSort
 * @author: IT_小白
 * @date 2023-05-30
 * @Description:
 */
public class BubbleSort {

	public static void bubbleSort(int[] arr) {
		if(arr == null || arr.length <= 0)return ;
		for (int i = 0; i < arr.length; i++) {
			for (int j = 1; j < arr.length - i; j++) {
				if(arr[j] < arr[j-1]) {
					int temp = arr[j];
					arr[j] = arr[j-1];
					arr[j-1] = temp;
				}
			}
		}
	}
	
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		bubbleSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

选择排序

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。重复第二步,直到所有元素均排序完毕。

/**
 * 选择排序
 * @ClassName: SelectionSort
 * @author: IT_小白
 * @date 2023-05-31
 * @Description:
 */
public class SelectionSort {
	
	public static void selectionSort(int[] arr) {
		if(arr == null && arr.length <= 0) return ;
		
		for (int i = 0; i < arr.length; i++) {
			//获取此次循环中最小值
			int minIndex = i;
			for (int j = i + 1; j < arr.length; j++) {
				if(arr[j] < arr[minIndex]) {
					minIndex = j;
				}
			}
			if(minIndex != i) {
				int temp = arr[minIndex];
				arr[minIndex] = arr[i];
				arr[i] = temp;
			}
		}
	}
	
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		selectionSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

插入排序

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

/**
 * 插入算法
 * @ClassName: InsertSort
 * @author: IT_小白
 * @date 2023-05-31
 * @Description:
 */
public class InsertSort {
	
	public static void insertSort(int[] arr) {
		if(arr == null && arr.length <= 0)return;
		//以索引0位置的数作为有序序列
		for (int i = 1; i < arr.length; i++) {
			//用来记录要插入的值
			int temp = arr[i];
			int j = i;
			while(j > 0 && temp < arr[j - 1]) {
				arr[j] = arr[j - 1];
				j--;
			}
			//说明插入到前面了
			if(j != i) {
				arr[j] = temp;
			}
		}
	}
	
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		insertSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

希尔排序

选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1; 按增量序列个数 k,对序列进行 k 趟排序;
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1
时,整个序列作为一个表来处理,表长度即为整个序列的长度。

/**
 * 希尔排序
 * @ClassName: ShellSort
 * @author: IT_小白
 * @date 2023-05-31
 * @Description:
 */
public class ShellSort {
	
	public static void shellSort(int[] arr) {
		int length = arr.length,temp;
		
		for(int step = length / 2;step >= 1;step /= 2) {
			for(int i = step;i < length;i++) {
				temp = arr[i];
				int j = i - step;
				while(j >= 0 && arr[j] > temp) {
					arr[step + j] = arr[j];
					j -= step;
				}
				arr[j + step] = temp;
			}
		}
	}
	
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		shellSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

归并算法

申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列; 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置; 重复步骤 3 直到某一指针达到序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾。

/**
 * 归并算法
 * @ClassName: MergeSort
 * @author: IT_小白
 * @date 2023-05-31
 * @Description:
 */
public class MergeSort {
	
	/**
	 * 
	 * @param arr 原数组
	 * @param left 左索引
	 * @param right 右索引
	 * @param temp 临时数组
	 */
	public static void mergeSort(int[] arr,int left,int right,int[] temp) {
		if(left < right) {
			int mid = (left + right) / 2;
			//向左拆分递归
			mergeSort(arr, left, mid, temp);
			//向右拆分递归
			mergeSort(arr, mid+1, right, temp);
			//拆分后合并
			merge(arr,left,right,mid,temp);
		}
	}
	/**
	 *	由于不断拆分重组,所以每半边的数据都是有序的,
	 *	所以在新的一轮重组过程就需要检查左边元素是否都小于右边元素,并将正确的顺序放到临时数组中,最终替换对应位置的原数组。
	 * @param arr 原数组
	 * @param left 左索引
	 * @param right 右索引
	 * @param mid 中间索引
	 * @param temp 临时数组
	 */
	private static void merge(int[] arr,int left,int right,int mid,int[] temp) {
		
		int i = left,j = mid + 1,index = 0;
		
		//用左边序列跟右边序列进行比较
		while(i <= mid && j <= right ) {
			if(arr[i] < arr[j]) {
				temp[index++] = arr[i++];
			} else {
				temp[index++] = arr[j++];
			}
		}
		//说明左边序列还有未排序的有序数据
		while(i <= mid) {
			temp[index++] = arr[i++];
		}
		//说明右边序列还有未排序的有序数据
		while(j <= right) {
			temp[index++] = arr[j++];
		}
		int resultIndex = left;
		index = 0;
		//将临时数组中的数据填充回原数组
		while(resultIndex <= right) {
			arr[resultIndex++] = temp[index++];
		}
	}
	
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		mergeSort(arr, 0, arr.length-1, new int[arr.length] );
		System.out.println(Arrays.toString(arr));
	}
}

快速排序

从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

/**
 * 快速排序
 * @ClassName: QuickSort
 * @author: IT_小白
 * @date 2023-06-01
 * @Description:
 */
public class QuickSort {
	
	public static void quickSort(int[] arr,int left,int right) {
		if(arr == null || arr.length <= 0 || left > right)return;
		
		int start = left,end = right,key = arr[left];
		
		while(start < end) {
			//从后往前比较
			while(start < end && arr[end] >= key) {
				end--;
			}
			//再从前往后比较
			while(start < end && arr[start] <= key) {
				start++;
			}
			//交换值
			if(start < end) {
				int temp = arr[start];
				arr[start] = arr[end];
				arr[end] = temp;
			}
		}
		arr[left] = arr[start];
		arr[start] = key;
		//向左递归
		quickSort(arr, left, end - 1);
		//向右递归
		quickSort(arr, end + 1, right);
	}
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		quickSort(arr, 0, arr.length - 1);
		System.out.println(Arrays.toString(arr));
	}
}

堆排序

创建一个堆 H[0……n-1];
把堆首(最大值)和堆尾互换;
把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
重复步骤 2,直到堆的尺寸为 1。

/**
 * 堆排序
 * @ClassName: HeapSort
 * @author: IT_小白
 * @date 2023-06-01
 * @Description:
 */
public class HeapSort {
	
	private static void heapSort(int[] arr) {
		if(arr == null && arr.length <= 0)return;
		int length = arr.length;
		//构建堆
		buildHeap(arr,length);
		for (int i = length - 1; i >= 0; i--) {
			//将堆顶元素与末尾元素调换
			int temp = arr[0];
			arr[0] = arr[i];
			arr[i] = temp;
			//长度-1隐藏队尾元素
			length--;
			//将堆顶元素下沉,使目前最大的元素浮到堆顶
			sink(arr, 0, length);
		}
	}

	private static void buildHeap(int[] arr, int length) {
		//由于使用的是一维数组模拟堆结构,所以构建时从中间开始
		for(int i = (int)Math.floor(length / 2) ; i >= 0;i--) {
			//下沉元素
			sink(arr, i, length);
		}
	}
	private static void sink(int[] arr,int index,int length) {
		//左右节点 和 当前节点
		int leftChild = (index * 2) + 1;
		int rightChild = (index * 2) + 2;
		int present = index;
		if(leftChild < length && arr[leftChild] > arr[present]) {
			//下标变动
			present = leftChild;
		}
		if(rightChild < length && arr[rightChild] > arr[present]) {
			//下标变动
			present = rightChild;
		}
		if(index != present) {
			int temp = arr[present];
			arr[present] = arr[index];
			arr[index] = temp;
			
			//继续下沉
			sink(arr, present, length);
		}
	}
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		heapSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

计数排序

(1)找出待排序的数组中最大和最小的元素
(2)统计数组中每个值为i的元素出现的次数,存入数组C的第i项
(3)对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
(4)反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

/**
 * 计数排序
 * @ClassName: CountSort
 * @author: IT_小白
 * @date 2023-06-01
 * @Description:
 */
public class CountSort {
	
	public static void countSort(int[] arr) {
		if(arr == null && arr.length <= 0)return ;
		//获取最大值
		int maxValue = arr[0];
		for (int i = 1; i < arr.length; i++) {
			if(maxValue < arr[i]) {
				maxValue = arr[i];
			}
		}
		//设置桶
		int[] bucket = new int[maxValue + 1];
		for (int i = 0; i < arr.length; i++) {
			bucket[arr[i]]++;
		}
		//从桶中取值
		int index = 0;
		for (int i = 0; i < bucket.length; i++) {
			while(bucket[i] > 0) {
				arr[index++] = i;
				bucket[i]--;
			}
		}
	}
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		countSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

桶排序

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:
1、在额外空间充足的情况下,尽量增大桶的数量
2、使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中

/**
 * 桶排序
 * @ClassName: BucketSort
 * @author: IT_小白
 * @date 2023-06-01
 * @Description:
 */
public class BucketSort {

	/**
	 * 桶排序
	 * @param arr 原数组
	 * @param bucketSize 设置桶的系数
	 */
	public static void bucketSort(int[] arr,int bucketSize) {
		if(arr == null && arr.length <= 0)return ;
		//获取最大值和最小值
		int maxValue = arr[0],minValue = arr[0];
		for (int i = 1; i < arr.length; i++) {
			if(maxValue < arr[i]) {
				maxValue = arr[i];
			}
			if(minValue > arr[i]) {
				minValue = arr[i];
			}
		}
		
		//设置桶
		int bucketCount = (int)Math.floor((maxValue - minValue) / bucketSize) + 1;
		int[][] buckets = new int[bucketCount][0];
		
		for (int i = 0; i < arr.length; i++) {
			int index = (int)Math.floor((arr[i] - minValue) / bucketCount);
			buckets[index] = arrAppend(buckets[index], arr[i]);
		}
		
		int arrIndex = 0;
		for(int[] bucket : buckets) {
			if(bucket.length <= 0) {
				continue;
			}
			//对桶中元素进行排序,这里调用的快排算法
			QuickSort.quickSort(bucket, 0, bucket.length - 1);
			for(int value : bucket) {
				arr[arrIndex++] = value;
			}
		}
	}
	
	/**
	 * 自动扩容并填值
	 * @param arr
	 * @param value
	 * @return
	 */
	private static int[] arrAppend(int[] arr,int value) {
		arr = Arrays.copyOf(arr, arr.length + 1);
		arr[arr.length - 1] = value;
		return arr;
	}
	
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,9,1,3,14};
		bucketSort(arr,5);
		System.out.println(Arrays.toString(arr));
	}
}

基数排序

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。

/**
 * 基数排序
 * @ClassName: RadixSort
 * @author: IT_小白
 * @date 2023-06-01
 * @Description:
 */
public class RadixSort {
	
	public static void radixSort(int[] arr) {
		if(arr == null && arr.length <= 0) return ;
		
		//获取最大值的位数
		int maxNumLength = getMaxNumLength(arr);
		//帮助数组元素获取对应位数数值
		int mid = 10,div = 1;
		for (int i = 0; i < maxNumLength; i++ ,mid *= 10,div *= 10) {
			//创建临时数组
			int[][] temps = new int[mid * 2][0];
			
			for (int j = 0; j < arr.length; j++) {
				//此设计可用于比较负数
				int index = ((arr[j] % mid) / div) + mid;
				temps[index] = arrAppend(temps[index], arr[j]);
			}
			
			//将临时数组中的数据按顺序倒入原数组中
			int index = 0;
			for(int[] temp : temps) {
				for(int value : temp) {
					arr[index++] = value;
				}
			}
		}
	}
	
	/**
	 * 获取数组中最大值的位数
	 * @param arr
	 * @return
	 */
	private static int getMaxNumLength(int[] arr) {
		int maxValue = arr[0],maxNumLength = 0;
		for (int i = 1; i < arr.length; i++) {
			if(maxValue < arr[i]) {
				maxValue = arr[i];
			}
		}
		for(int i = maxValue ; i > 0; i /= 10) {
			maxNumLength++;
		}
		return maxNumLength;
	}
	
	/**
	 * 自动扩容并填值
	 * @param arr
	 * @param value
	 * @return
	 */
	private static int[] arrAppend(int[] arr,int value) {
		arr = Arrays.copyOf(arr, arr.length + 1);
		arr[arr.length - 1] = value;
		return arr;
	}
	
	public static void main(String[] args) {
		int[] arr = new int[] {23,3,5,12,-10,9,1,3,14,-4};
		radixSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值