排序

  • 冒泡排序
    1.思路:遍历所有数每一轮通过交换把最大的数挪到最后。
    2.最差、平均、复杂度都是O(n²),最好是O(n)。
	static void bubbleSort(int[] A) {
		for(int n=A.length-1;n>=0;n--){	
			for(int i=0;i<n;i++){
				if(A[i]>A[i+1]){
					int temp=A[i];
					A[i]=A[i+1];
					A[i+1]=temp;
				}
			}
		
		}
		
	}
  • 选择排序
    1.思路:从前面开始放 每一轮选出一个最小的记录其下标 在和前面未排序的数交换。
    2.最差、平均、最好复杂度都是O(n²)。
static void selectSort(int[] A) {
		for (int i = 0; i < A.length; i++) {
			int minIndex = i;
			int min = A[i];
			for (int j = i; j < A.length; j++) {
				if (A[j] < min) { //如果有更小的 记录其下标
					minIndex = j;
				}

			}
			int temp = A[i];
			A[i]=A[minIndex];
			A[minIndex]=temp;
		
		}


	}
  • 插入排序
    1.思路:通过插入保证当前遍历的数前面那一段有序(包括当前的数)
    2.比如 3,4,5,2,6,7 当前遍历的数为2, 2和前面所有的数比较(2前面的数往前挪)把2放到合适的位置。
    2.最差、平均、复杂度都是O(n²),最好是O(n)。
static void insertSort(int[] A) {
		// 遍历所有数
		for (int i = 1; i < A.length; i++) {
			// 与前一个数对比 如果小了要遍历前面所有的数 把它插入到最小的位置
			if (A[i] < A[i - 1]) {
				int temp = A[i];
				int j;
				// 遍历之前的数
				for (j = i - 1; j >= 0 && temp < A[j]; j--) {
					A[j + 1] = A[j];
				}
				// 把当前数放到合适的位置
				A[j + 1] = temp;
			}
		}
	}
  • 希尔排序
  1. 思路 分组插入排序 按一定的增量分组
    选gap=A.length/2 增量序列{n/2,(n/2)/2…1}
  2. 平均时间复杂度O(nlogn) 其他好的增量序列效率会提高。
static void shellSort(int[] A) {
		for (int d = A.length / 2; d > 0; d /= 2) {
			// 以增量为d插入排序
			for (int i = d; i < A.length; i++) {

				for (int j = i - d; j >= 0; j -= d) {
					if (A[j] > A[j + d]) {
						int temp = A[j + d];
						A[j + d] = A[j];
						A[j] = temp;
					}

				}

			}

		}

	}
  • 快速排序
  1. 分治法(用递归实现)定义一个基数 基数左边的比基数小
    基数右边的比基数大,分别对左边和右边排序。
  2. 时间复杂度O(nlogn)最坏的情况相当于冒泡排序O(n²)每一次取到的不是靠中间的值。
	public  static void quick(int[] arr,int low,int high) {
		if(low<high) {
		int q=partition2(arr,low,high);
		quick(arr,low,q-1);
		quick(arr,q+1,high);
		}
	}
	// 双向扫描法
	public static int partition2(int[] arr,int low,int high) {
		int stard=arr[low]; //主元
		int p=low+1;		//左边的指针
		int q=high;			//右边的指针
		while(p<=q) {
			while(p<=q&&arr[p]<=stard)p++;
			while(p<=q&&arr[q]>=stard)q--;
			if(p<q) {
			int temp=arr[p];
			arr[p]=arr[q];
			arr[q]=temp;
			}
		}
//		最后 p(包含p)后面的数都是比主元大的 q(包含q)前面的数都是比主元小的     
		int temp=arr[q];
		arr[q]=stard;
		arr[low]=temp;
		return q;
	}
	// 一遍单向扫描
	public static int partition(int[] arr, int low, int high) {
		int stard=arr[low];
		int p=low+1; 
		int q=high;
		while(p<=q) {
			if(arr[p]<=stard) {
				p++;
			}else {
				int temp=arr[p];
				arr[p]=arr[q];
				arr[q]=temp;
				q--;
			}
			
		}
//		最后 p(包含p)后面的数都是比主元大的 q(包含q)前面的数都是比主元小的     
		int temp=arr[q];
		arr[q]=stard;
		arr[low]=temp;	
		return q;
	}


  • 归并排序
    1.利用分治的思想 将问题分解成一些小的问题递归求解
    2.在将分阶段得到的答案合并在一起
    3.最坏,平均,最好时间复杂度O(nlogn)。
static void mergeSort(int[] A, int low, int high) {
		if (low < high) {
			int mid = low + ((high - low) >> 1);
			mergeSort(A, low, mid);
			mergeSort(A, mid + 1, high);
			merge(A, low, mid, high);
		}
	}

	static void merge(int[] A, int low, int mid, int high) {
		int[] helper=new int[A.length];
  //先把原数组拷贝到辅助数组
		System.arraycopy(A, low, helper, low, high - low + 1);
	
		int left = low;// 左侧队伍的头指针
		int right = mid+1; // 右侧队伍的头指针      *
		int current = low; // 当前原数组的指针
		while (left <= mid && right <= high) {
			if (helper[left] <= helper[right]) {
				A[current] = helper[left];
				left++;
				current++;
			} else {
				A[current] = helper[right];
				right++;
				current++;

			}
		}
		while (left <= mid) {
			A[current] = helper[left];
			left++;
			current++;

		}
		while(right<=high) {
			A[current] = helper[right];
			current++;
			right++;
		}
	}
  • 堆排序
    1.利用堆这种数据结构,是一种选择排序,先构造成一个大顶堆或者小顶推(逆序)。
    3.最坏,平均,最好时间复杂度O(nlogn)。
	static void MinHeap(int[] A){
		int n=A.length;
		for (int i=(n-1)/2;i>=0;i--){
			MinHeapFixDown(A,i,n);
		}

	}
	static void MinHeapFixDown(int[] A,int i,int n){
		// 找到左右孩子
		int left=2*i+1;
		int right=2*i+2;
		// 左孩子越界 左孩子是叶子节点 找到左右孩子中的min
		if(left>=n) return;
		int min=left;
		if(right<n&&A[right]<A[left])
		min=right;
		// 	如果A[i]比min小 则不用调整
		if(A[i]<=A[min])return;
		//	否则找到小的和A[i]交换
		int temp=A[i];
		A[i]=A[min];
		A[min]=temp;	
		//  判断 i变为min 递归解决
		MinHeapFixDown(A,min,n);
		
	}
//	堆排序 时间复杂度为o(NlogN) 
	static void sort(int[] A,int n){
		//先将数组小顶堆化
		MinHeap(A);
			for(int x=n-1;x>=0;x--) {
		//把堆顶和最后一个元素对调
		  int temp=A[x];
		   A[x]=A[0];
		  A[0]=temp;
			
		//缩小堆的范围 对堆进行向下调整
		MinHeapFixDown(A,0,x);
			}
	}
  • 计数排序
    1.用辅助数组的下标来记录原数组中的值以达到空间换时间
    2.时间复杂度O(n+k)。
public static int[] getRandomArr(int length, int min, int max) {
        int[] arr = new int[length];
        for (int i = 0; i < length; i++) {
            arr[i] = (int) (Math.random() * (max + 1 - min) + min);
        }
        return arr;
    }
	public static void main(String[] args) {
		int[] arr=getRandomArr(4,1,10);
		System.out.println(Arrays.toString(arr));
		countSort(arr);
		System.out.println(Arrays.toString(arr));

	}

	// 用辅助数组的下标来记录原数组中的值以达到空间换时间
	// 线性复杂度
	static void countSort(int[] A){
	// 找到原数组的最大值作为辅助数组的长度
		int max=A[0];
		for(int x:A){
			if(x>max)
			max=x;
		}
	// 辅助数组
		int[] helper=new int[max+1];
		for(int x:A){
			helper[x]++;
		
		}
		int index=0;
		//回填
		 for(int i=0;i<helper.length;i++){
			 while (helper[i] > 0) {
				 A[index++] = i;
				 helper[i]--;
			 }
		 }

}
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值