数据结构

排序

1.时间复杂度为O(n)的排序,计数排序,桶排序,基数排序
时间复杂度为O(n)的排序,计数排序,桶排序,基数排序
时间复杂度为O(n)的三种排序算法
比较
1.时间复杂度比较
在这里插入图片描述
在这里插入图片描述
稳定性:
稳定性
稳定性是指,比如a在b前面,a=b,排序后,a仍然应该在b前面,这样就算稳定的。

桶排序中,假如升序排列,a已经在桶中,b插进来是永远都会a右边的(因为一般是从右到左,如果不小于当前元素,则插入改元素的右侧)

所以桶排序是稳定的

PS:当然了,如果采用元素插入后再分别进行桶内排序,并且桶内排序算法采用快速排序,那么就不是稳定的

稳定性算法: 基数排序 , 直接插入排序 , 冒泡排序, 归并排序

不稳定性算法: 桶排序(不确定), 二分插入排序,希尔排序, 快速排序, 简单选择排序,堆排序
在这里插入图片描述
在这里插入图片描述

算法乱序时间复杂度有序时间复杂度
插入排序O(N^2)O(N)
希尔排序O(N^2)O(N)
冒泡排序O(N^2)O(N)
基数排序O(N)O(N)
桶排序O(N)
计数排序O(N)
归并排序O(NlogN)O(NlogN)
快速排序O(NlogN)O(N^2)
堆排序O(NlogN)

2.空间复杂度比较

算法空间复杂度
插入排序O(1)
希尔排序O(1)
冒泡排序O(1)
基数排序O(N)
桶排序O(N+M) M是额外辅助空间(桶数量)
计数排序O(N)
归并排序O(N)
快速排序O(1)
堆排序O(1)

各种排序的代码实现及其排序一轮后的效果(选择)

插入排序

分为排好序和未排好序,未排好序的跟排好序的从右往左比较,找到合适的位置插入。

import java.util.Arrays;

public class Insert {
	public static int[] insertSort(int[] arr) {
		if(arr==null ||arr.length==0)
			return null;
		for(int i=1;i<arr.length;i++) {
			int tmp = arr[i];
			int j;
			for(j=i;j>0 && arr[j-1]>tmp;j--) {
				arr[j] =arr[j-1];
			}
			arr[j] = tmp;
		}
		return arr;
	}
	public static void main(String[] args) {
		int[] array = {38,65,97,76,13,27,49};
        System.out.println("排序前的数据为:");
        System.out.println(Arrays.toString(array));
        System.out.println("排序后的数据为:");
        System.out.println(Arrays.toString(insertSort(array)));
	}

}

快速排序

总体递归:
利用快速排序的结果是左边比基准元素小,右边比基准元素大。分为左右两端,不断递归。
非递归:思想是 两个指针互相比较的思想,在编程题中很常用。
快排的延申:由快速排序得到的查找数组中第K小的元素的算法:

import java.util.Arrays;

public class QuickSort {
	public static void quicksort(int [] nums,int left,int right) {
		if(left>=right)
			return;
		int privotIndex = partion(nums,left,right);
//		System.out.println(Arrays.toString(nums));
//		System.out.println(Arrays.toString(nums));
		quicksort(nums,left,privotIndex-1);
		quicksort(nums,privotIndex+1,right);
	}
	public static int partion(int[] nums,int left,int right) {
		//进行排序交换,并返回基准元素的位置
		int privot = nums[left];
		int i=left;
		//int i =left+1;易错点:这样会造成已经排好序的与left+1再次交换
		int j =right;
		while(i!=j) {
			while(i<j && nums[j]>privot) {
				j--;
			}
			while(i<j && nums[i]<=privot) {
				i++;
			}
			if(i<j) {
				int tmp = nums[i];
				nums[i] =nums[j];
				nums[j] =tmp;
				
			}
		}
		int tmp = privot;
		nums[left] =nums[i];
		nums[i] =tmp;
		return i;
	}
	//由快速排序得到的查找数组中第K小的元素的算法:
	public static int Select(int[] nums,int k) {
		int i=0;
		int j=nums.length-1;
		while(i<j) {
			int temp =  partion(nums,i,j);
			if(temp<k-1)
				i= temp+1;
			else if(temp>k-1)
				j=temp-1;
			else
				return nums[k-1];
		}
		return nums[k-1];
	}
	public static void main(String[] args) {
		int[] nums = new int[] {4,7,6,5,3,2,8,1};
//		int[] nums = new int[] {6, 5, 7, 8};
//		int[] nums = new int[] {8,1,4,9,0,3,5,2,7,6};
		quicksort(nums,0,nums.length-1);
		System.out.println(Arrays.toString(nums));
		System.out.println(Select(nums,3));
	}

}

希尔排序

小灰希尔不稳定

import java.util.Arrays;

public class XiEr {
	public static void sort(int [] arr) {
		int d = arr.length;
		while(d>1) {
			d= d/2;
			for(int x=0;x<d;x++) {
				for(int i =x+d;i<arr.length;i=i+d) {
					int tmp = arr[i];
					int j;
					for(j=i-d;j>=0&&arr[j]>tmp;j=j-d) {//j>=0,而不是j>0
						arr[j+d] =arr[j];
					}
					arr[j+d] = tmp;
				}
			}
		}
	}
	public static void main(String[] args) {
		int[] arr = {5,3,9,12,6,1,7,2,4,11,8,10};
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}

}

计数排序

小灰的计数排序](https://mp.weixin.qq.com/s/WGqndkwLlzyVOHOdGK7X4Q)
普通

import java.util.Arrays;

public class jishu1 {
	public static int[] countSort(int[] array) {
		//1.得到数列的最大值
		int max = array[0];
		for(int i=1;i<array.length;i++) {
			if(array[i]>max) {
				max = array[i];
			}
		}
		//2.根据数列的最大值确定统计数组的长度
		int[] countArray = new int[max+1];
		//3.遍历数列,填充统计数组
		for(int i =0;i<array.length;i++) {
			countArray[array[i]]++;
		}
		//System.out.println(Arrays.toString(countArray));
		//4.遍历统计数组,输出结果
		int index = 0;
		int [] sortedArray = new int [array.length];
		for(int i=0;i<countArray.length;i++) {
			for(int j =0;j<countArray[i];j++) {
				sortedArray[index++] =i;
			}
		}
		return sortedArray;
	}
	public static void main(String[] args) {
		int[] array = new int [] {4,4,6,5,3,2,8,1,7,5,6,0,10};
        int[] sortedArray = countSort(array);
        System.out.println(Arrays.toString(sortedArray));
	}

}

90,91…分布

public class jishuyouhua {
	public static int[] countSort(int[] array) {
		//1.得到数列的最大值和最小值,并计算差值d
		int max = array[0];
		int min = array[0];
		for(int i = 1;i<array.length;i++) {
			if(array[i]>max) {
				max = array[i];
			}
			if(array[i]<min) {
				min = array[i];
			}
		}
		int d = max - min;
		//2.创建统计数组并统计对应元素的个数
		int[] countArray = new int[d+1];
		for(int i =0;i<array.length;i++) {
			countArray[array[i] - min]++;
		}
		int index = 0;
		int [] sortedArray = new int [array.length];
		for(int i=0;i<countArray.length;i++) {
			for(int j =0;j<countArray[i];j++) {
				sortedArray[index++] =i+min;
			}
		}
		return sortedArray;
	}
	public static void main(String[] args) {   
		int[] array = new int [] {95,94,91,98,99,90,99,93,91,92};
        int[] sortedArray = countSort(array);
        System.out.println(Arrays.toString(sortedArray));
	}

}

改进:稳定排序
统计数组做变形,后面的元素等于前面元素之和:相同的元素可以按照固定顺序排列

public class jishuyouhua {
	public static int[] countSort(int[] array) {
		//1.得到数列的最大值和最小值,并计算差值d
		int max = array[0];
		int min = array[0];
		for(int i = 1;i<array.length;i++) {
			if(array[i]>max) {
				max = array[i];
			}
			if(array[i]<min) {
				min = array[i];
			}
		}
		int d = max - min;
		//2.创建统计数组并统计对应元素的个数
		int[] countArray = new int[d+1];
		for(int i =0;i<array.length;i++) {
			countArray[array[i] - min]++;
		}
//		System.out.println(Arrays.toString(countArray));
		//3.统计数组做变形,后面的元素等于前面元素之和
		for(int i =1;i<countArray.length;i++) {
			countArray[i] +=countArray[i-1];
		}
//		System.out.println(Arrays.toString(countArray));
		//4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
		int [] sortedArray = new int[array.length];
		for(int i= array.length-1;i>=0;i--) {
			sortedArray[countArray[array[i]-min]-1] = array[i];
			countArray[array[i]-min]--;
		}

		return sortedArray;
	}

堆排序

//堆排序,不稳定,时间O(nlogn),空间O(1)
import java.util.Arrays;
public class Heap {
	public static void heapContrust(int[] arr) {
		//初始化堆,构建大顶堆
		for(int i=0;i<arr.length;i++) {
			int childindex = i;
			int fatherindex = (childindex - 1)/2;
			while(arr[childindex] > arr[fatherindex]) {
				int tmp = arr[childindex];
				arr[childindex] = arr[fatherindex];
				arr[fatherindex] = tmp;
				childindex = fatherindex;
				fatherindex = (childindex - 1)/2;
			}
		}
	}
	public static void heapAdjust(int[] arr, int index,int size) {
		int left = 2*index + 1;
		int right = 2*index + 2;
		while(left < size) {
			int maxIndex;
			if(arr[left] < arr[right] && right < size)
				maxIndex = right;
			else
				maxIndex = left;
			if(arr[index] > arr[maxIndex])
				maxIndex = index;
			if(index == maxIndex)
				break;
			int tmp = arr[maxIndex];
			arr[maxIndex] = arr[index];
			arr[index] = tmp;
			index = maxIndex;
			left = 2*index + 1;
			right = 2*index + 2;
		}
	}
	
	public static void heapSort(int[] arr) {
		heapContrust(arr);
		int size = arr.length;
		while(size > 0) {
			int tmp = arr[0];
			arr[0] = arr[size-1];
			arr[size-1] = tmp;
			size --;
			heapAdjust(arr, 0, size);
		}
	}
	public static void main(String[] args) {
		int[] arr = {3,6,8,5,7,3,9,2};
		heapSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

需要修改:
最好引入 swap函数, 因为交换使用比较多。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值