排序算法

在这里插入图片描述
冒泡排序

冒泡排序是基于交换思想的排序方法。它将相邻的两个元素加以比较,若左边元素值大于右边元素值,则将这两个元素交换位置;若左边元素值小于右边元素值,则这两个元素位置不变。右边元素继续和下一个元素进行比较,重复这个过程,直到比较到最后一个元素为止

class BubbleSort{
	/**
	 * 冒泡排序复杂度为O(n^2)
	 * 外层for控制循环次数
	 * 内层for负责交换
	 * @param arr
	 */
	public static void Bubblesort(int arr[]) {
		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;
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
				if(!flag) {//在一趟排序中,一次交换都没有发生
					break;
				}else {
					flag = false;//重置flag ,进行下次排序
				}
			}
		}	
	}
}

插入排序

把n个元素的数列分成有序(前)和无序(后)的两部分,每次处理就是将无序的数列中第一个元素与有序数列的元素从后到前比较,找到插入位置,将该元素插入到有序数列的适当的最终的位置上(稳定排序)

class insert{
	/**
	 * insertIndex >= 0保证给insertVal插入位置,不越界
	 * insertVal < arr[insertIndex] 待插入的数,没有找到插入位置
	 * 需要将arr[insertIndex]后移
	 * @param arr
	 */
	public static void sort(int[] arr) {
		for(int i=1;i<arr.length;i++) {
			int insertVal = arr[i];//定义待插入的数
			int insertIndex = i-1;//即arr[i]前面数的下标
			
			while(insertIndex >= 0 && insertVal < arr[insertIndex]) {
				arr[insertIndex + 1] = arr[insertIndex];
				insertIndex--;
			}
			//退出循环说明插入位置找到,insertIndex + 1
			arr[insertIndex+1] = insertVal;
		}
		
		
	}
}

选择排序

第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的第二小文章。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

class Select{

	public static void SelectSort(int[] arr) {
		for(int i = 0;i < arr.length-1;i++) {
			int minIndex = i;
			int min = arr[i];
			for(int j = i+1;j<arr.length;j++) {
				if(min>arr[j]) {//说明假定的最小值不是最小
					min=arr[j];//重置min
					minIndex=j;//重置minIndex
				}
			}
			if(minIndex != i) {
				//将最小值,放在arr[0],即交换
				arr[minIndex] = arr[i];
				arr[i] = min;
			}
		}
	}
}

希尔排序(不稳定排序)

实质上是一种分组插入方法
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量
=1(
<
…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

/**
	 * 希尔排序(交换式)
	 * @param arr
	 */
	public static void sort(int[] arr) {
		int temp = 0;
		for(int gap = arr.length / 2;gap > 0;gap /=2) {
			for(int i = gap; i < arr.length;i++) {
				//遍历各组中所有的元素(共gap组,每组有个元素),步长为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;
					}
				}
				
			}
		}
	}
	/**
	 * 采用移位法-》希尔排序
	 * @param arr
	 */
	public static void sort1(int[] arr) {
		//增量gap,并逐步缩小增量
		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;
					}
					//当退出while后,就给temp找到插入位置
					arr[j] = temp;
				}
			}
		}
	}

快速排序

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

public static void quickSort(int[] arr,int left,int right) {
		int L = left ;//左下标
		int R = right;//右下标
		int mid = arr[(right+left)/2];//mid中轴值
		int temp = 0;//临时变量
		//使比mid小的放左边
		while(L<R) {
			//在mid左边找到大于mid的
			while(arr[L]<mid) {
				L += 1;	
			}
			//在mid右边找到小于mid的
			while(arr[R]>mid) {
				R -= 1;	
			}
			//如果L>R说明mid的左右两边的值,已经左边小于右边
			if(L >= R) {
				break;
			}
			//交换
			temp = arr[L];
			arr[L] = arr[R];
			arr[R] = temp;
			//如果交换完后,发现arr[L]==mid ,相等 -- ,前移
			if(arr[L] == mid) {
				R -= 1;
			}
			//如果交换完后,发现arr[R]==mid ,相等 -- ,前移
			if(arr[R] == mid) {
				L -= 1;
			}
		}
		//如果L=R,必须L++,R--,否则为出现栈溢出
		if(L == R) {
			L += 1;
			R -=1;
		}
		//向左递归
		if(left < R) {
			quickSort(arr, left, R);
		}
		//向右递归
		if(right > L) {
			quickSort(arr, L, right);
		}
	}

归并排序(分治法、稳定)

	/**
	 * 拆分方法
	 * @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);
			//到合并
			mergeSort(arr, left, right, mid, temp);
		}
	}
	
	/**
	 * 合并的方法
	 * @param arr 待排序数组
	 * @param left 左边有序序列的初始索引
	 * @param right	右边索引
	 * @param mid 中间索引
	 * @param temp 中转数组
	 */
	public static void mergeSort(int[] arr,int left,int right,int mid,int[] temp) {
		int i = left;//左边有序序列初始索引
		int j = mid + 1;//右边有序序列初始索引
		int t = 0;//指向temp数组的当前索引
		//(一)
		//先把左右两边有序数据按规则填充到temp中
		//直到有一边处理完为止
		while(i<=mid && j<=right) {
			//如果左边有序序列当前元素小于右边,将左边拷贝到temp中
			//然后i++;t++
			if(arr[i]<arr[j]) {
				temp[t] = arr[i];
				t += 1;
				i += 1;
						
			}else {
				temp[t] = arr[j];
				t += 1;
				j += 1;
			}
		}
		//(二)
		//把剩余所有数据拷入temp中
		while(i<=mid) {//左边有序序列还有元素,填充到temp
			temp[t] = arr[i];
			t += 1;
			i += 1;
			
		}
		while(j<=right) {//左边有序序列还有元素,填充到temp
			temp[t] = arr[j];
			t += 1;
			j += 1;
			
		}
		//(三)
		//把temp中数据拷入arr中
		t = 0;
		int tempLeft = left;
		while(tempLeft <= right) {
			arr[tempLeft] = temp[t];
			t++;
			tempLeft++;
		}
	}

基数排序(桶排序,稳定)

/**
	 * 基数排序,也叫桶排序
	 * 1、得到数组中最大的数
	 * 2、得到最大数是几位数
	 * 3、创建二维数组包含10个一维数组
	 * 4、创建一个数组长度为10的一维数组,记录每个桶中存放的数据个数
	 * 5、将数组中数据按照个位、十位、百位等对10取余获得给位置上的数,并存入二维数组中
	 * 6、按照一维数组中存储的数,按桶的顺序取出所有元素,放入原数组
	 * @param arr
	 */
	public static void radixSort(int arr[]) {
		//1、得到数组中最大的数的位数
		int max = arr[0];//假设第一个数就是最大数
		for(int i=1;i<arr.length;i++) {
			if(arr[i]>max) {
				max=arr[i];
			}
		}
		//得到最大数是几位数
		int maxLength=(max+"").length();
		//1、二维数组包含10个一维数组
		//2、为了防止放入数据的时候,数据溢出,则每一个堆数组(桶),大小定为arr.length
		//3、基数排序是使用空间换时间的算法
		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];
				bucketElementCounts[digitOfElement]++;
			}
			//按照这个桶的顺序(按照一维数组的下标依次取出数据,放入原来的数组)
			int index=0;
			//
			for(int k=0;k<bucketElementCounts.length;k++) {
				//如果桶中有数据,有数据,我们才放入到原数据
				if(bucketElementCounts[k] != 0) {
					//循环该桶即第k个桶(即第k个一维数组),放入
					for(int m=0;m<bucketElementCounts[k];m++) {
						arr[index++]=bucket[k][m];
					}
				}
				//第i+1轮处理后,需要将每个bucketElementCOunts[k]=0
				bucketElementCounts[k]=0;
			}
		}
		
	}

堆排序

/**堆排序
	 * 1)将无序序列构建成一个堆,根据升序降序选择大顶堆或小顶堆
	 * 2)将堆顶元素与末尾元素进行交互,将最大元素沉到数组末端
	 * 3)重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序
	 */
	
	public static void heapSort(int[] arr) {
		int temp=0;
		System.out.println("堆排序");
		//将无序序列构建成一个堆,根据升序降序选择大顶堆或小顶堆
		for(int i=arr.length/2-1;i>=0;i--) {
			adjustHead(arr, i, arr.length);
		}
		//将堆顶元素与末尾元素进行交互,将最大元素沉到数组末端
		//重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序
		for(int j=arr.length-1;j>0;j--) {
			//交换
			temp = arr[j];
			arr[j]=arr[0];
			arr[0]=temp;
			adjustHead(arr, 0, j);
		}
		System.out.println("==========调整后=============");
		System.out.println(Arrays.toString(arr));
	}
	/**
	 * 功能:将以i对应的非叶子结点的树调整为大顶堆
	 * @param arr  待调整的数组
	 * @param i		表示非叶子结点在数组中的索引
	 * @param length	对多少个元素进行调整
	 */
	public static void adjustHead(int arr[],int i,int length) {
		int temp = arr[i];
		/**
		 * 1、k=i*2+1 k是i结点的左子结点
		 */
		for(int k=i*2+1;k<length;k=k*2+1) {
			if(k+1<length && arr[k]<arr[k+1]){//左子结点的值小于右子结点的值
				k++;//k指向右子结点
			}
			if(arr[k]>temp) {//r如果子结点大于父节点
				arr[i]=arr[k];//把较大的值赋给当前结点
				i=k;//让i指向k,继续循环比较
			}else {
				break;
			}
		}
		//当for循环结束后,已经将以i为父结点的树的最大值,放在了最顶端(局部)
		arr[i]=temp;//将temp值放到调整后的位置
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值