排序算法

在这里插入图片描述
尚硅谷JAVA数据结构

交换排序

冒泡排序

基本思想:通过对待排序序列从前向后,依次比较相邻元素的值,若发现逆序则交换
在这里插入图片描述

第一次优化:排序过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行交换,就说明序列有序

public class BubbleSort {
	public static void main(String[] args) {
		int arr[] = {3,9,-1,10,-2};
		
		//·过程 从小到大
		int temp = 0;
		//·优化:定义一个标识变量,
		boolean flag = false;
		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]) {
					//·进行了交换 设置flag=true
					flag=true;
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
				System.out.print("第" + (i + 1) + "趟" + "第" + (j + 1) + "次结果");
				System.out.print(Arrays.toString(arr));
				System.out.println();
			}
			System.out.print("第"+ (i + 1) +"趟最终:");
			System.out.print(Arrays.toString(arr));
			System.out.println();
			if(!flag) {//·没有进行交换  说明已经有序
				
				break;
			}else {
				flag = false;//·重置flag
			}
		}
		System.out.println(Arrays.toString(arr));
	}
}

在这里插入图片描述
第二次优化:利用一个标志位,记录一下当前第 i 趟所交换的最后一个位置的下标,在进行第 i+1 趟的时候,只需要内循环到这个下标的位置就可以了,因为后面位置上的元素在上一趟中没有换位,这一次也不可能会换位置了

public class BubbleSort {
	public static void main(String[] args) {
		int arr[] = {6,4,7,5,1,3,2};
		
		//·过程 从小到大
		int temp = 0;
		//·优化:定义一个标识变量,
		boolean flag = false;
		//·记录最后依次交换的位置
		int tempPosition = 0;
		int len = arr.length-1;
		for(int i = 0;i < arr.length-1 ; i++) {
			
			for(int j = 0;j < len ;j++) {//·循环到最后一次交换的位置就行
				if(arr[j]<arr[j+1]) {
					//·进行了交换 设置flag=true
					flag=true;
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
					tempPosition = j;
				}
				System.out.print("第" + (i + 1) + "趟" + "第" + (j + 1) + "次结果");
				System.out.print(Arrays.toString(arr));
				System.out.println();
			}
			len = tempPosition;
			System.out.print("第"+ (i + 1) +"趟最终:");
			System.out.print(Arrays.toString(arr));
			System.out.println();
			if(!flag) {//·没有进行交换  说明已经有序
				
				break;
			}else {
				flag = false;//·重置flag
			}
		}
		System.out.println(Arrays.toString(arr));
	}
}

快速排序

基本思想:快速排序是对冒泡排序的一种改进,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据段都比另外一部分的所有数据都小,然后再按此方法对这两部分分别进行快速排序,整个排序过程可以递归进行。
在这里插入图片描述
推荐查看添加链接描述

public class QuickSort {

	public static void main(String[] args) {
		int[] arr = {-9,78,0,23,-567,70,11,23,36524,123,56,-123,-23};
		quickSort(arr, 0, arr.length-1);
		System.out.println(Arrays.toString(arr));
	}
	public static void quickSort(int[] arr,int l ,int r) {
		if(l < r) {
			int i = l;
			int j = r;
			int x = arr[i];
			while(i < j) {
				//从右向左找到小于x 的数来填充arr[i]
				while(i < j && arr[j]>=x) {
					//找到 j-1
					j--;
				}
				//·循环结束后找到值把找到的这个数填充道a[i],先判断j-1后i j是否相等
				if(i < j) {
					arr[i] = arr[j];
					i++;
				}
				//·从左向右找到大于x的数填充道arr[j]
				while(i< j && arr[i] < x) {
					i++;
				}
				if(i < j) {
					arr[j] = arr[i];
					j--;
				}
			}
			//·循环结束后 i的位置就是x在序列中的最终位置
			arr[i]= x;
			quickSort(arr, l, i-1);
			quickSort(arr, i+1, r);
		}
	}
}

选择排序

直接选择排序

基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
在这里插入图片描述

/**
 * 1.选择排序一共有数组大小-1轮排序
 * 2.每一个排序又是一个循环,规则如下
 * 	2.1先假定当前的数是最小的
 * 	2.2然后和后面的数比较,如果发现有比当前数小(大),就重新确定最小数,并得到下标
 * 	2.3当遍历完时,得到本轮最小数和下标
 * 	2.4交换
 * @author DC
 *
 */
public class SimpleSelectionSort {
	public static void main(String[] args) {
		int[] arr= {10,34,119,1,5,7,45};
		selectSort(arr);
	}
	public static void selectSort(int arr[]) {
		
		//假定第一个数是最小值
		for(int i = 0;i < arr.length;i++) {
			int minIndex = i;
			int min = arr[minIndex];
			for(int j = i+1; j <arr.length; j++ ) {
				if(min>arr[j]) {//min不是最小数
					minIndex = j;
					min = arr[j];
				}
			}
			if(minIndex!=i) {
				arr[minIndex] = arr[i];
				arr[i] = min;
			}
			System.out.println("第"+(i+1)+"轮");
			System.out.println(Arrays.toString(arr));
		}
	}
	
}

堆排序

堆是具有以下性值的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆;每个节点的值都小于或等于其左右孩子节点的值,称为小顶堆。

在这里插入图片描述
在这里插入图片描述
一般升序采用大顶堆,降序采用小顶堆

堆排序的基本思想

  1. 将待排序序列构造成一个大顶堆
  2. 将根节点与末尾元素交换
  3. 将剩余元素重新构造成一个大顶堆,重复2

非递归

public class HeapSort {

	public static void main(String[] args) {
		//·升序排列
		int[] arr = {4,6,8,5,9,123,2,-12,-13};
		headSort(arr);
 	}
	
	public static void headSort(int[] arr) {
		int temp = 0;
		System.out.println("堆排序");
		//分步
		//adjustHeap(arr, 1, arr.length);
		//System.out.println("第一次"+Arrays.toString(arr));
		
		//adjustHeap(arr, 0, arr.length);
		//System.out.println("第二次"+Arrays.toString(arr));
		
		//1.完整构建大顶堆
		for(int i = arr.length /2 - 1; i >= 0 ;i--) {
			adjustHeap(arr, i, arr.length);
		}
		
		//2.将对顶元素与末尾元素交换,将最大元素沉到数组末端
		//3.重新调整结构使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行,直到整个序列有序
		for(int j = arr.length -1 ; j>0 ;j--) {
			//·交换
			temp = arr[j];
			arr[j] =arr[0];
			arr[0] =temp;
			adjustHeap(arr, 0, j);
		}
		System.out.println(Arrays.toString(arr));
	}
	//·将一个数组调整成一个大顶堆
	/**
	 * 功能:将以i节点为跟的子树调整为大顶堆
	 * @param arr 数组
	 * @param i 非叶子节点 在数组中的索引
	 * @param length 有多少个非叶子节点
	 */
	public static void adjustHeap(int[] arr,int i ,int length) {
		//·取出当前元素的值
		int temp = arr[i];
		//·开始调整
		//1.k 是 i节点的左子节点
		for(int k = i * 2 + 1;k < length; k = k * 2 + 1) {
			if( arr[k] < arr[k+1] && k + 1 < length ) {//·左子节点的值小于右子节点
				k++;//指向右子节点
			}
			if(arr[k] > temp) {//·子节点大于父节点
				arr[i] = arr[k];//·将较大的值赋给父节点
				i = k;//i指向k 继续循环比较
			}else {
				break;
			}
		}
		//·结束循环后 已经将以i为父节点的树调整完毕
		arr[i] = temp;//将temp的值放到调整后的位置
	}
}

递归

public class HeapSort2 {
	public static void main(String[] args) {
		int[] arr = {4,6,8,5,9,123,2,-12,-13};
		heapSort(arr);
	}
	
	public static void heapSort(int[] arr) {
		//构建大顶堆
		for(int i = arr.length / 2 - 1; i >= 0; i-- ) {
			adjustHeap(arr, i, arr.length);
		}
		
		//交换堆顶和末尾元素
		int temp = 0;
		for(int j = arr.length -1 ; j>0 ;j--) {
			//·交换
			temp = arr[j];
			arr[j] =arr[0];
			arr[0] =temp;
			adjustHeap(arr, 0, j);
		}
		System.out.println(Arrays.toString(arr));
	}
	
	public static void adjustHeap(int[] arr, int i, int len) {
		//左子节点
		int left = 2 * i + 1;
		//右子节点
		int right = 2 * i + 2;
		//默认当前节点值最大
		int largestIndex = i;
		if(left < len && arr[left] > arr[largestIndex]) {
			largestIndex = left;
		}
		if(right < len && arr[right] > arr[largestIndex]) {
			largestIndex = right;
		}
		
		if(largestIndex != i) {
			//交换
			int temp = arr[i];
			arr[i] = arr[largestIndex];
			arr[largestIndex] = temp;
			//交换之后 子节点值变了 继续调整
			adjustHeap(arr, largestIndex, len);
		}
	}
}

插入排序

直接插入排序

基本思想:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表只包含一个元素,无序表包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把他的排序码依次与有序元素的排序码比较,将它插入到合适的位置,使之成为新的有序表

在这里插入图片描述

public class InsertSort {
	public static void main(String[] args) {
		int[] arr= {40,34,119,1,51,7,45};
		insertSort(arr);
	}
	
	public static void insertSort(int[] arr) {
		//·使用for循环从二个数开始
		for(int i = 1;i< arr.length;i++) {
			//·保存第i位的值
			int insertVal = arr[i];
			//·前一位的位置
			int insertIndex = i - 1;
			//insertIndex>= 0 保证在给insertVal找位置时不越界
			//如果insertVal <arr[insertIndex]),就是还没找到位置
			//需要将insertIndex位的数往后移一位
			while(insertIndex >=0 && insertVal <arr[insertIndex]) {
				arr[insertIndex + 1]  = arr[insertIndex];
				insertIndex--;
			}
			arr[insertIndex + 1] = insertVal;
			System.out.println(Arrays.toString(arr));
		}
	} 
}

在这里插入图片描述

希尔排序

基本思想:把数组按下标的一定增量分组,对每组使用直接插入排序算法,随着增量逐渐减少,每组包含的元素 越来越多,当增量减至1时,整个文件被分成一组,结束。
在这里插入图片描述

public class ShellSort {
	public static void main(String[] args) {
		int[] arr = {8,9,1,7,2,3,5,4,0};
	}
	public static void ShellSort(int arr[]) {
		
		//第一轮:将10个数据分成5组
		/*int temp = 0;
		for(int i =5;i<arr.length;i++) {
			//遍历各组中所有的 元素,步长5
			for(int j = i-5;j >= 0;j-=5) {
				if(arr[j] > arr[j+5]) {
					//如果当前元素大于同组的那个数,则交换
					temp = arr[j];
					arr[j] = arr[j+5];
					arr[j+5] = temp;
				}
			}
		}
		*/
		//交换法
		for(int gap = arr.length/2;gap > 0;gap /=2 ) {
			int temp = 0;
			for(int i =gap;i<arr.length;i++) {
				//·遍历各组中所有的 元素,步长gap
				for(int j = i-gap;j >= 0;j-=gap) {
					if(arr[j] > arr[j+gap]) {
						//·如果当前元素大于同组的那个数,则交换
						temp = arr[j];
						arr[j] = arr[j+gap];
						arr[j+gap] = temp;
					}
				}
			}
		}
	}
	//移动法
	public static void ShellSort2(int[] arr) {
		
		for(int gap = arr.length/2;gap > 0;gap /=2 ) {
			//对第gap个元素,逐个对其所在的组进行直接插入排序
			for(int i =gap;i < arr.length;i++) {
				int j =i;
				int temp = arr[j];
				if(arr[j] < arr[j-gap]) {
					while(j-gap >=0 && temp < arr[j-gap]) {
						//移动
						arr[j] = arr[j-gap];
						j -= gap;
					}
					//退出循环后,就给temp找到位置
					arr[j] = temp;
				}
			}
		}
	}
}

归并排序

在这里插入图片描述

public class MergeSort {

	public static void main(String[] args) {
		int[] arr = {8,4,5,7,1,3,6,2};
		int[] temp = new int[arr.length];
		mergeSort(arr, 0, arr.length-1, temp);
		System.out.println(Arrays.toString(arr));
	}
	
	//分+合方法
	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, mid, right, temp);
		}
	}
	
	//合并的方法
	/**
	 * 
	 * @param arr 原始数组
	 * @param left 左边有序序列的初始索引
	 * @param mid 中间索引
	 * @param right 右边索引
	 * @param temp 中转数组
	 */
	public static void merge(int[] arr,int left,int mid ,int right, int[] temp) {
		int i = left;// 初始化i,左边有序序列的初始索引
		int j = mid + 1;//`初始化j,右边有序序列的初始索引
		int t = 0;
		
		//(一)
		//·先把左右两边(有序)的数组按照规则填充道temp数组
		//·直到有一边为空
		while( i <= mid && j <= right ) {
			//·左边序列的当前元素小于等于右边序列的当前元素
			//·将左边 的元素拷贝到temp
			//i++,t++
			if(arr[i] <= arr[j]) {
				temp[t++] = arr[i++];
				//i +=1;
				//t +=1; 
			}else {
				temp[t++] = arr[j++];
				//j +=1;
				//t +=1;
			}
		}
		
		
		//(二)
		//·把还有剩余的数组填充到temp
		while(i <=mid) {//·说明左边还剩有元素
			temp[t++] = arr[i++];
			//t +=1;
			//i +=1;
		}
		
		while(j <=right) {//·说明右边还剩有元素
			temp[t++] = arr[j++];
			//t +=1;
			//j +=1;
		}
		
		//(三)
		//·将temp数组拷贝到arr
		//t = 0;
		//int tempLeft = left;
		//while (tempLeft <= right) {
		//	arr[tempLeft] = temp[t];
		//	 t +=1;
		//	 tempLeft +=1;
		//}
		int k =0;
		for(int templeft = left; templeft <= right; templeft++) {
			arr[templeft] = temp[k++];
		}
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值