排序
注意:本系列排序都为升序,降序同理。
冒泡
/* 冒泡排序
* 遍历所有元素,相邻元素两两比较,如果与原定顺序(升序或降序)不同,则交换
* 遍历一次就会得到一个最大元素(升序)或最小元素(降序)
* 稳定,t:O(n^2),s:O(1)
* @param array
*/
public static void bubbleSort(int[] array) {
if(array==null) return; //空数组
for(int i=0;i<array.length-1;i++) {
boolean flag=true; //冒泡优化:设置一个标志位
for(int j=0;j<array.length-1-i;j++) {
if(array[j]>array[j+1]) {
int temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
flag=false;
}
}
if(flag) break; //标志位没有改变,表示没有执行if内容,前面的元素已经有序了,不用再遍历比较
}
}
快排
/* 快排 递归实现
* 快速排序采用 分治,从元素中挑一个作为基准数,
* 遍历元素,比基准数小的放左边,大的放右边,
* 同样的方法对基准数左右两个子数组进行 递归 操作
* 不稳定,t:O(nlogn),s:O(logn)
*/
private static int quickOne(int[] array,int left,int right) {
int key=array[left];
while(left<right) {
while(left<right && array[right]>=key) right--; //两个while不能交换顺序
array[left]=array[right];
while(left<right && array[left]<key) left++;
array[right]=array[left];
}
array[left]=key;
return left;
}
private static void quickSort(int[] array,int left,int right) {
int mid=quickOne(array,left,right);
if(left<mid-1) quickSort(array,left,mid-1);
if(mid+1<right) quickSort(array,mid+1,right);
}
public static void quickSort(int[] array)
{
if(array==null) return;
quickSort(array,0,array.length-1);
}
public static void quickSort2(int[] array) { //快排 非递归
if(array==null) return;
Stack<Integer> stack=new Stack<>(); //栈,先进后出
stack.push(0);
stack.push(array.length-1);
while(!stack.isEmpty())
{
int right=stack.pop();
int left=stack.pop();
int mid=quickOne(array,left,right);
if(left<mid-1)
{
stack.push(left);
stack.push(mid-1);
}
if(mid+1<right)
{
stack.push(mid+1);
stack.push(right);
}
}
}
归并
/* 归并排序
* 将已有序的子序列合并,得到完全有序的序列
* 稳定,t:O(nlogn),s:O(n)
*/
private static void mergeOne(int[] array,int left,int mid,int right) {
if(array[mid]<=array[mid+1]) return;
for(int i=mid+1;i<=right;i++)
{
for(int j=i;j>left;j--)
{
if(array[j]<array[j-1])
{
int temp=array[j];
array[j]=array[j-1];
array[j-1]=temp;
}
else break;
}
}
}
private static void mergeSort(int[] array,int left,int right)
{
int mid=(left+right)/2;
if(left<mid) mergeSort(array,left,mid);
if(mid+1<right) mergeSort(array,mid+1,right);
mergeOne(array,left,mid,right);
}
public static void mergeSort(int[] array)//递归归并
{
if(array==null) return;
mergeSort(array,0,array.length-1);
}
public static void mergeSort2(int[] array)//非递归归并
{
if(array==null) return;
Queue<Integer> queue=new LinkedList<>();
for(int i=0;i<array.length;i++)
{
queue.add(i);
queue.add(i);
}
while(!queue.isEmpty())
{
int left1=queue.poll();
int right1=queue.poll();
int left2=queue.poll();
int right2=queue.poll();
if(right1+1!=left2)
{
queue.add(left1);
queue.add(right1);
left1=left2;
right1=right2;
left2=queue.poll();
right2=queue.poll();
}
mergeOne(array,left1,right1,right2);
if(queue.isEmpty()) break;
queue.add(left1);
queue.add(right2);
}
}
选择排序
/* 选择排序
* 任选一个(通常选第一个元素)作为最小值,与其后面的元素一一比较,如果找到比它更小的,则交换
* 每次得到一个最小值
* 不稳定,t:O(n^2),s:O(1)
*/
public static void selectSort(int[] array) {
if(array==null) return;
for(int i=0;i<array.length-1;i++) {
int min=i; //下标
for(int j=i;j<array.length;j++) { //遍历,找出最小值下标
if(array[min]>array[j]) min=j; //交换,min始终是较小元素的下标
}
if(min!=i) { //交换过了,将遍历出的最小元素放到起始位置
int temp=array[min];
array[min]=array[i];
array[i]=temp;
}
}
}
直接插入排序
/* 直接插入排序
* 假定前i个元素有序了,依次遍历数据,将当前数据插入到适当位置,形成i+1个由于元素
* 从第二个元素开始,依次设置为待插入元素,从后往前 比较,确定要插入的位置
* 稳定,t:O(n^2),s:O(1)
*/
public static void insertSort(int[] array) {
if(array==null) return;
for(int i=1;i<array.length;i++) {
int temp=array[i]; //当前待插入的元素
int j=i-1;
while(j>=0 && array[j]>temp) {
array[j+1]=array[j]; //元素后移,给待插入元素让位
j--;
}
array[j+1]=temp;
}
}
二分法排序
/* 二分法排序(直接插入排序的改进)
* 在速度上有提升
* 直接插入是与前面的逐个比较,二分法则是二分比较
* 稳定,t:O(nlogn),s:O(1)
*/
public static void halfSort(int[] array) {
for(int i=1;i<array.length;i++) {
int temp=array[i]; //待插入元素
int left=0;
int right=i-1;
int mid=-1;
while(left<=right) {
mid=left+(right-left)/2; //二分了
if(array[mid]>temp) right=mid-1;
else left=mid+1;
}
for(int j=i-1;j>=left;j--) array[j+1]=array[j];
array[left]=temp; //插入
}
}
希尔排序
/* 希尔排序 (插入排序的改进)
* 将整个数组分割成 若干个子序列,分别进行直接插入排序
* 待基本有序时,再对全部数据依次直接插入排序
* 不稳定,t:O(n^3/2),s:O(1)
*/
public static void shellSort(int[] array) {
if(array==null) return;
int d=array.length/2; //以d的长度划分子区域
while(d>0) {
for(int i=0;i+d<array.length;i++) {
if(array[i]>array[i+d]) {
int temp=array[i];
array[i]=array[i+d];
array[i+d]=temp;
}
}
d--;
}
}
堆排序
/* 堆排序
* 利用堆(近似完全二叉树的数据结构排序
* 不稳定,s:O(nlogn),t:(1)
*/
public static void heapSort(int[] array) {
if(array==null) return;
int n=array.length;
while(n>1) {
for(int i=n/2;i>=1;i--) {
if(2*i+1<=n && array[i-1]<array[2*i])
{
int t=array[i-1];
array[i-1]=array[2*i];
array[2*i]=t;
}
if(array[i-1]<array[2*i-1])
{
int temp=array[i-1];
array[i-1]=array[2*i-1];
array[2*i-1]=temp;
}
}
int temp=array[0];
array[0]=array[n-1];
array[n-1]=temp;
n--;
}
}
基数排序
/* 基数排序
* 是一种基于非比较的整数排序算法,原理是将整数按 位数 切割成不同的数字,
* 然后按每个不同 数位 分别比较
* 原始算法思想是将所有待比较的数值统一为同样的数位长度,不足的前面补零,然后从 最低位 开始依次进行依次排序
* 直到所有数据有序
* 稳定,t:O(n*k),s:O(n+k)
* n是数据个数,k是数据位数
*/
public static void radixSort(int[] array) {
if(array==null) return;
int max=array[0];
for(int i=1;i<array.length;i++)
{
if(max<array[i])
{
max=array[i];
}
}
MyHashMap<Integer> myHash=new MyHashMap<>(10);
int k=1;
System.out.println("max="+max);
while(max>0)
{
k=k*10;
for(int i=0;i<array.length;i++)
{
int key=array[i]%k/(k/10);
System.out.print(key+" ");
myHash.add(key, array[i]);
}
System.out.println();
myHash.hashToArray(array);
max=max/10;
}
}
7万+

被折叠的 条评论
为什么被折叠?



