## 排序算法
关于排序算法分析注意要点:
1、插入排序:
打扑克:手里面大的是排好序的,另外是待排序的,一张一张插入后要保证有序
未插入的从已排序的末尾一个个往前比较,找到合适的位置插入(比较过的都往后面移动一位,刚好待排的当前元素被已排序的最后一个元素覆盖)。
public class InsertSort {
public static void main(String[] args)
{
int[] a={9,8,7,6,5,4,0};
int n=a.length;
for(int i=1;i<n;i++)//默认0已经排好序了
{
// [8,9]
int data=a[i];//防止i位置被移位的时候占用了
int j;
for(j=i-1;j>=0;j--)//去排好序的地方走
//注意移位置是向后面移,所以从哪里开始比较!
{
if(a[j]>data)//比较对象是data,而非a[i]
{
a[j+1]=a[j];//占用也站的是data所在的i位置
}
else
{
break;//不用比较了
}
}
a[j+1]=data;//跳出比较再赋值
System.out.println("第"+i+"次比较结果");
for(j=0;j<n;j++)
{
System.out.print(a[j]+" ");
}
System.out.println();
}
}
}
时间复杂度: o( n^2) 最好的情况:O(n);//每次都走break;内层时间O(1)
——如何优化?
分段,为了让break执行的越多越好,效率越高;
2、希尔排序:
public static void main(String[] args) {
int[] a = {9, 8, 7, 6, 5, 4, 0};
int len = a.length;
int add = len / 2;//7/2=3
int i = 0;
for(;add>=1;add/=2)//3/2=1
{
System.out.println("add="+add);
for(i=add;i<len;i++)//i=1和插入排序一样
{
System.out.println("i="+i);
int temp=a[i];
int j=i;
for(j=i-add;j>=0;j-=add)//j=9
{
System.out.println("temp="+temp);
if(a[j]>temp)//9>6?
{
System.out.println("a[j]="+a[j]);
a[j+add]=a[j];//6=9
System.out.println(a[j]);
}
else{
break;//不需要再对j做-add了!!!!!!!!!!非常很重要
}
}
System.out.println("a[j+add]"+a[j+add]);
a[j+add]=temp;//
// System.out.println(temp);
for(int k=0;k<len;k++)
{
System.out.print(a[k]+" ");
}
System.out.println("___________");
}
}
3、归并排序
先分治,再合并
public class MergeSort {
/**
* 1、分治最小长度为2
* 2、比较大小交换位置
* 3、两两合并
*/
private int[] arr;
public MergeSort(int[] inputarr) {
arr = inputarr;
}
public void merge_sort() {
int len = arr.length;
int[] result = new int[len];
merge_sort_execut(0, len - 1, result);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public void merge_sort_execut(int l, int r, int[] result) {
if (l >= r)
return;
int len = r - l, mid = len / 2 + l;//安全写法
int l1 = l, r1 = mid;
int l2 = mid + 1, r2 = r;
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
*****merge_sort_execut(l1, r1, result);
merge_sort_execut(l2, r2, result);
//合并*****
int index = l;
while (l1 <= r1 && l2 <= r2) {
result[index++] = arr[l1] < arr[l2] ? arr[l1++] : arr[l2++];
}
while (l1 <= r1) {
result[index++] = arr[l1++];
}
while (l2 <= r2) {
result[index++] = arr[l2++];
}
for (index = l; index <= r; index++) {
arr[index] = result[index];
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
4、选择排序
O(n^2)
1、分为有序和无序
2、从无序中找到最小值,排在有序的后面【和有序的后面那个元素交换——>因而‘不稳定’排序】
public static void main(String[] args)
{
int[] arr={9,1,8,7,6,5,4,3};
int len=arr.length;
for(int i=0;i<len;i++)//每个位置都判断
{
int minIndex = i;
// 找到未排序部分中的最小元素的索引
for (int j = i + 1; j < len; j++) {//找到里面最小的,也包括data[i],因而minindex=i
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 将最小元素与未排序部分的第一个元素交换位置[不稳定排序]
//可以加一个if(minIdex!=i)
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
for(int i=0;i<len;i++)
{
System.out.println(arr[i]);
}
}
5、冒泡排序
O(n^2)
1、每个泡泡都要处理
2、每次处理都是两两相邻的比较[稳定的,判断的时候用>,而非>=],将大的往后传递【最终每一趟都把最大的传递到最后面了】
public static void main(String[] args)
{
int[] a={9,8,7,6,5,0};
for(int i=0;i<a.length-1;i++)//循环次数【最后就剩一个泡泡了无需比较了,所以n-1】
{
//
for(int j=0;j<a.length-1-i;j++)//因为每一趟都把最大的移动到了最末尾,所以最后的就没有必要比较了,因而减去i
{
if(a[j]>a[j+1])
{
int temp=a[j+1];//第三个变量
a[j+1]=a[j];
a[j]=temp;
// 用加减[无需多一个变量]
// a[j+1]=a[j+1]+a[j];
// a[j]=a[j+1]-a[j];
// a[j+1]=a[j+1]-a[j];
}
}
}
for(int elem:a)
{
System.out.print(elem);
}
}
每一趟最坏的情况:每个都交换O(n^2);
如何优化?
对于与已经排好序的则变成了O(n);
boolean flag=false;
for(int j=0;j<a.length-1-i;j++)//因为每一趟都把最大的移动到了最末尾,所以最后的就没有必要比较了,因而减去i
{
if(a[j]>a[j+1])
{
int temp=a[j+1];//第三个变量
a[j+1]=a[j];
a[j]=temp;
// 用加减
// a[j+1]=a[j+1]+a[j];
// a[j]=a[j+1]-a[j];
// a[j+1]=a[j+1]-a[j];
flag=true;//
}
}
if(!flag)//无交换;说明相邻三的元素左《中《右
{
break;
}
6、快速排序
1、找到一个基准,将数组分为{小于基准数的}+基准数+{大于基准数的};
logn次分割,每一次有n次的(基准)排序:O(nlogn)
2、如何实现?
3、为什么要区别右指针和左指针谁先走!
4、最坏的情况N次分治,N个排序:O(n^2)
区别:
public class FastSort {
static int[] a = {9, 0, 8, 7, 5, 3, 6, 2};
public static void main(String[] args) {
fastsort_execut(a,0,a.length-1);
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]+" ");
}
}
public static void fastsort_execut(int[] data,int l,int r) {
int i = l;
int j = r;
// int basic=data[0];
if(l>=r)
{
return;
}
int base = data[l];//注意必须先判断再给base赋值
while (i<j)
{
while(i<j&&data[j]>=base)//!!!!!一定是右指针先迈出去
{
j--;
}
while(i<j&&data[i]<=base)
{
i++;
}
if(i<j)//一定要加上
{//少一个变量的空间
data[i]=data[i]+data[j];
data[j]=data[i]-data[j];
data[i]=data[i]-data[j];
}
}
data[l]=data[j];
data[j]=base;
// for(int k=l;k<=r;k++)
// {
// System.out.print(data[k]);
// }
// System.out.println("中间结果");
// int l1=0,r1=i-1,l2=i+1,r2=r;
fastsort_execut(data,l,i-1);
fastsort_execut(data,i+1,r);
}
}
关于递归: