Java数据结构与算法笔记——排序算法(全)

该篇博客详细展示了多种排序算法的实现,包括冒泡排序、优化后的冒泡排序、选择排序、插入排序、希尔排序(交换式和位移式)、快速排序以及归并排序。博主通过代码实现并测试了这些排序算法,最后使用基数排序和快速排序对一个大数组进行排序,对比了它们的时间效率。
摘要由CSDN通过智能技术生成
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class PX {
	public static void main(String[] args) {
//		int[] arr = new int[80000];
//		for(int i=0;i<80000;i++) {
//			arr[i]=(int)(Math.random()*800000);
//		}
//		PXExample pX = new PXExample();
//		Date date1=new Date();
//		SimpleDateFormat simple1=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
//		String date1Str=simple1.format(date1);
//		System.out.println(date1Str);
//		pX.maoPao2(arr);
//		Date date2=new Date();
//		String date2Str=simple1.format(date2);
//		System.out.println(date2Str);
		PXExample pX = new PXExample();
//		int arr[] = new int[10];
//		int temp2[] = new int[10];
		int arr[] = new int[10000000];
		for (int i = 0; i < 10000000; i++) {
			arr[i] = (int) (Math.random() * 100000000);
		}
		// pX.maoPao1(arr);
		// pX.maoPao2(arr);
		// pX.xuanZe(arr);
		// pX.chaRu(arr);
		// pX.shellSort1(arr);
		// pX.shellSort2(arr);
		Date date1 = new Date();
		SimpleDateFormat simple1 = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
		String date1Str = simple1.format(date1);
		System.out.println(date1Str);
		// pX.mergeSort(arr, 0, arr.length - 1, temp2);
		// pX.kuaiSu(arr, 0, arr.length - 1);
		pX.radixSort(arr);
		;
		Date date2 = new Date();
		String date2Str = simple1.format(date2);
		System.out.println(date2Str);
		// System.out.println("快速排序:" + Arrays.toString(arr));
		// System.out.println("归并排序:" + Arrays.toString(arr));
	}

}

class PXExample {
	static int temp;

	// 交换
	public static void swap(int arr[], int i, int j) {
		temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

	// 冒泡排序
	public void maoPao1(int[] arr) {
		int temp = 0;
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) {
					swap(arr, j, j + 1);
				}
			}
		}
		System.out.println("冒泡排序:" + Arrays.toString(arr));
	}

	// 冒泡排序优化
	public void maoPao2(int[] arr) {
		int temp = 0;
		boolean flag;
		for (int i = 0; i < arr.length - 1; i++) {
			flag = false;
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) {
					swap(arr, j, j + 1);
					flag = true;
				}
			}
			if (!flag)
				break;
		}
		System.out.println("优化后的冒泡排序:" + Arrays.toString(arr));
	}

	// 选择排序
	public void xuanZe(int arr[]) {
		int minIndex;
		for (int i = 0; i < arr.length - 1; i++) {
			minIndex = i;
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[minIndex] > arr[j]) {
					minIndex = j;
				}
			}
			swap(arr, minIndex, i);
		}
		System.out.println("选择排序:" + Arrays.toString(arr));
	}

	// 插入排序
	public void chaRu(int arr[]) {
		for (int i = 1; i < arr.length; i++) {
			int insertVal = arr[i];
			int insertIndex = i - 1;
			while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
				arr[insertIndex + 1] = arr[insertIndex];
				insertIndex--;
			}
			arr[insertIndex + 1] = insertVal;
		}
		System.out.println("插入排序:" + Arrays.toString(arr));
	}

	// 希尔排序(交换式)
	public void shellSort1(int[] arr) {
		for (int gap = arr.length / 2; gap > 0; gap /= 2) {
			for (int i = gap; i < arr.length; i++) {
				for (int j = i - gap; j >= 0; j -= gap) {
					if (arr[j] > arr[j + gap]) {
						swap(arr, j, j + gap);
					}
				}
			}
		}
		System.out.println("希尔排序(交换式):" + Arrays.toString(arr));
	}

	// 希尔排序(位移式)
	public void shellSort2(int[] arr) {
		for (int gap = arr.length / 2; gap > 0; gap /= 2) {
			for (int i = gap; i < arr.length; i++) {
				int j = i;
				int temp1 = arr[j];
				if (arr[j - gap] > arr[j]) {
					// while中的判断顺序不能改变,如果改变可能会导致j-gap<0导致数组越界
					while (j - gap >= 0 && arr[j - gap] > temp1) {
						arr[j] = arr[j - gap];
						j -= gap;
					}
					arr[j] = temp1;
				}
				// arr[j + gap] = temp1;如果把这行放在这里,可能当if语句没运行时,导致数组越界。
			}
		}
//		for (int gap = arr.length / 2; gap > 0; gap /= 2) {
//			for (int i = gap; i < arr.length; i++) {
//				int j = i;
//				int temp1 = arr[j];
//				if (arr[j] < arr[j - gap]) {
//					while (j - gap >= 0 && temp1 < arr[j - gap]) {
//						arr[j] = arr[j - gap];
//						j -= gap;
//					}
//					arr[j] = temp1;
//				}
//			}
//		}
		System.out.println("希尔排序:(位移式)" + Arrays.toString(arr));
	}

	// 快速排序
	public void kuaiSu(int arr[], int left, int right) {
		int l = left, r = right;
		int pivot = arr[(left + right) / 2];
		while (l < r) {
			while (arr[l] < pivot) {
				l++;
			}
			while (arr[r] > pivot) {
				r--;
			}
			if (l == r) {
				break;
			}
			swap(arr, l, r);
			if (arr[l] == pivot) {
				r--;
			}
			if (arr[r] == pivot) {
				l++;
			}
			/*
			 * if(arr[l]==pivot) { r--; } if(arr[r]==pivot) { l++; }
			 * 这些代码不能省略,如果省略会导致当数组中有重复的数字时,无妨推出
			 */
		}
		if (l == r) {
			l++;
			r--;
		}
		if (left < r) {
			kuaiSu(arr, left, r);
		}
		if (l < right) {
			kuaiSu(arr, l, right);
		}
	}

	public void quickSort(int arr[], int left, int right) {
		int l = left, r = right;
		int pivot = arr[(left + right) / 2];
		while (l < r) {
			while (arr[l] < pivot) {
				l++;
			}
			while (arr[r] > pivot) {
				r--;
			}
			if (l >= r) {// 这里可以用>=也可以用==
				break;
			}
			swap(arr, r, l);
			if (arr[r] == pivot) {
				l++;
			}
			if (arr[l] == pivot) {
				r--;
			}
		}
		if (l == r) {
			r--;
			l++;
		}
		if (l < right) {
			quickSort(arr, l, right);
		}
		if (left < r) {
			quickSort(arr, left, r);
		}
	}

	// 归并排序
	public void guiBingPaiXu(int arr[], int left, int right, int temp2[]) {
		if (left < right) {
			int mid = (right + left) / 2;
			guiBingPaiXu(arr, left, mid, temp2);
			guiBingPaiXu(arr, mid + 1, right, temp2);
			guiBing(arr, left, mid, right, temp2);
		}
	}

	public void guiBing(int arr[], int left, int mid, int right, int temp2[]) {
		int i = left, j = mid + 1;
		int t = 0;
		while (i <= mid && j <= right) {
			if (arr[i] <= arr[j]) {
				temp2[t++] = arr[i++];
			} else {
				temp2[t++] = arr[j++];
			}
		}
		while (i <= mid) {
			temp2[t++] = arr[i++];
		}
		while (j <= right) {
			temp2[t++] = arr[j++];
		}
		t = 0;
		while (left <= right) {
			arr[left++] = temp2[t++];
		}
	}

	// 分+合方法
	public 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, mid, right, temp);
		}
	}

	/**
	 *
	 * @param arr   要排序的数组
	 * @param left
	 * @param mid   中间索引
	 * @param right
	 * @param temp  中转数组
	 */
	public void merge(int[] arr, int left, int mid, int right, int[] temp) {
//        System.out.println("xxx");
		int i = left; // 初始化左边序列的初始索引
		int j = mid + 1;// 初始化右边序列的初始索引
		int t = 0;

		// (1)
		// 先把左右两边的(有序)的数据按照规则填到数组里面
		// 直到两边的有序序列有一边处理完为止
		while (i <= mid && j <= right) {
			// 左边有序序列的当前元素小于等于右边元素
			if (arr[i] <= arr[j]) {
				temp[t++] = arr[i++];
			} else {
				temp[t++] = arr[j++];
			}

		}

		// (2)
		// 把有剩余数据的一边数据依次完全填充到temp

		while (i <= mid) {
			temp[t++] = arr[i++];
		}

		while (j <= right) {
			temp[t++] = arr[j++];
		}

		// (3)
		// 将temp数组的元素拷贝到arr
		// 并不是每次都拷贝所有数据到原来的数组 从下往治
		t = 0;
		int tempLeft = left;
//        System.out.println("tempLeft = "+ tempLeft+",right = "+right);
		while (tempLeft <= right) {
			arr[tempLeft++] = temp[t++];
		}
	}

	// 基数排序
	public void jishu(int arr[]) {
		int temp1 = 0;
		int divisor = 1;
		while (true) {
			int zeroTime = 0;
			int[] k = new int[10];
			int bucket[][] = new int[10][arr.length];
			for (int i = 0; i < arr.length; i++) {
				// temp1 = (arr[i] / divisor)%10;
				temp1 = (arr[i] / divisor) % 10;
				if (temp1 == 0)
					zeroTime++;
				bucket[temp1][k[temp1]++] = arr[i];
			}
			divisor *= 10;
			if (zeroTime == arr.length)
				break;
			int sortTime = 0;
			for (int i = 0; i < 10; i++) {
				if (k[i] != 0) {
					for (int j = 0; j < k[i]; j++) {
						arr[sortTime++] = bucket[i][j];
					}
				}
			}
		}
		System.out.println("基数排序:" + Arrays.toString(arr));
	}

	public void radixSort(int arr[]) {
		// 先找到最大数的位数
		int max = arr[0];
		for (int i = 1; i < arr.length; i++) {
			if (arr[i] > max) {
				max = arr[i];
			}
		}
		int maxLength = (max + "").length();

		// 用这个二维数组表示桶
		int[][] bucket = new int[10][arr.length];

		// 用这个记录桶中数字的数量
		int[] bucketElementCounts = new int[10];

		// 开始循环
		for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
			for (int j = 0; j < arr.length; j++) {
				int digitOfElement = (arr[j] / n) % 10;
				bucket[digitOfElement][bucketElementCounts[digitOfElement]++] = arr[j];
			}
			// 把桶中的数据放入原来的数组中
			int index = 0;
			for (int k = 0; k < 10; k++) {
				if (bucketElementCounts[k] != 0) {
					for (int j = 0; j < bucketElementCounts[k]; j++) {
						arr[index++] = bucket[k][j];
					}
					bucketElementCounts[k] = 0;
				}
			}
		}

		// 输出结果
		//System.out.println("基数排序:" + Arrays.toString(arr));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值