赞
踩
目录
1、稳定性:在待排序的记录中,存在多个相同的关键字记录,若在排序前和排序后这些相同关键字的相对次序保持不变,则这种排序算法是稳定的,否则称为不稳定的。
①思想:将要插入的数据和前面比较,要是前面的小,结束比较,要是前面的大,元素后移,再次比较,直到遇到较小的,元素插入。
②代码实现:
- public static void insertSort(int[] a){
- int size=a.length;
- for(int i=1;i<size;i++){
- int j=i-1;
- int temp=a[i]; //后面会被覆盖
- for(;j>=0;j--){
- if(a[j]>temp){
- a[j+1]=a[j];
- }else {
- break;
- }
- }
- a[j+1]=temp;
- }
- }
③特性:
元素越接近有序,时间效率越高;
时间复杂度:O(n^2);空间复杂度:O(1);稳定性:稳定。
①思想:对元素进行分组,如有10个元素,先分成5组(元素间隔为5),对着5组进行插入排序;再分成2组(元素间隔为2),对这2组进行插入排序;最后分成1组(元素间隔为1),对着1组进行插入排序,此时插入排序时元素已经接近有序了。
②代码实现:
- public static void shellSort(int[] a){
- int size=a.length;
- while(size/2>=1){
- size/=2;
- shell(a,size);
- }
- }
-
- public static void shell(int[] a,int group){
- int size=a.length;
- for(int i=1;i<size;i++){
- int temp=a[i];
- int j=i-group;
- for(;j>=0;j-=group){
- if(a[j]>temp){
- a[j+group]=a[j];
- }else{
- break;
- }
- }
- a[j+group]=temp;
- }
- }
③特性:
是直接插入排序的优化。
时间复杂度:O(n^1.25)到O(1.6n^1.25);空间复杂度:O(1);稳定性:不稳定。
①思想:
从第一个数开始,每次找到待排序数的最小值,与第一个数交换位置;然后开始第二个数,每次找到待排序数的最小值,与第二个数交换位置......直到最后一个数结束。
②代码实现:
- public static void selectSort(int[] a){
- int size=a.length;
- for(int i=0;i<size-1;i++){
- int min=i;
- for(int j=i+1;j<size;j++){
- if(a[j]<a[min]){
- min=j;
- }
- }
- if(i!=min){
- swap(a,i,min);
- }
- }
- }
- public static void swap(int[] a,int m,int n){
- int temp=a[m];
- a[m]=a[n];
- a[n]=temp;
- }
③特性:
时间复杂度:O(n^2);空间复杂度:O(1);稳定性:不稳定。
①思想:
一个指针指向要排序数的最小值,一个指针指向要排序数的最大值,最小值放左边,最大值放右边,往中间遍历,但需注意:最大值在要排序数第一个的情况。
②代码实现:
- public static void selectSort2(int[] a){
- int size=a.length;
- int left=0;
- int right=size-1;
- while(left<right){
- int max=right;
- int min=left;
- for(int i=left;i<=right;i++){
- if(a[i]>a[max]){
- max=i;
- }else if(a[i]<a[min]){
- min=i;
- }
- }
- if(max==left){
- max=min;
- }
- if(min!=left){
- swap(a,min,left);
- }
- if(max!=right){
- swap(a,max,right);
- }
- left++;
- right--;
- }
- }
- public static void swap(int[] a,int m,int n){
- int temp=a[m];
- a[m]=a[n];
- a[n]=temp;
- }
①思想:
若是升序的话,建立大根堆,每次将堆顶元素与最后一个元素交换,前n-1个元素,以第一个父结点进行向下调整......直到交换结束。
若是降序的话,建立小根堆,每次将堆顶元素与最后一个元素交换,前n-1个元素,以第一个父结点进行向下调整......直到交换结束。
②代码实现:
- public static void buildPile(int[] a){
- int size=a.length;
- int parent=(size-2)/2;
- for(int i=parent;i>=0;i--){
- buildChildPile(a,i,size);
- }
- }
- public static void buildChildPile(int[] a,int parent,int size){
- int child=2*parent+1;
- while(child<size){
- if(child+1<size&&a[child]<a[child+1]){
- child=child+1;
- }
- if(a[child]>a[parent]){
- swap(a,child,parent);
- }
- parent=child;
- child=2*parent+1;
- }
- }
- public static void pileSort(int[] a){
- int size=a.length-1;
- while(size!=0){
- swap(a,0,size);
- buildChildPile(a,0,size-1);
- size--;
- }
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(1);稳定性:不稳定。
①思想:
将大的往左边放,每次遇到一个数,比后面数大,就往后交换。
②代码实现:
- public static void bubbleSort(int[] a){
- int size=a.length;
- boolean flag=true;
- for(int i=0;i<size-1;i++){
- for(int j=1;j<size-i;j++){
- if(a[j-1]>a[j]){
- swap(a,j-1,j);
- flag=false;
- }
- }
- if(flag){
- break;
- }
- }
- }
③特性:
时间复杂度:O(n^2);空间复制度:O(1);稳定性:稳定。
①思想:找到一个基准值,默认为left指针,right往左移,left往右移,如果right小于基准,left大于基准,两者交换,循环进行到left<right不满足,基准值要和最后一个left交换,接着划分区间进行判断,直到区间里只有一个元素结束。
②代码实现:
- public static void quickSort(int[] a){
- quickChild(a,0,a.length-1);
- }
- public static void quickChild(int[] a,int left,int right){
- if(left>=right){ //一个元素
- return;
- }
- int index=index(a,left,right); //进行交换,并找到基准值的位置
- quickChild(a,left,index-1); //左区间接着判断
- quickChild(a,index+1,right); //右区间接着判断
- }
- public static int index(int[] a,int left,int right){
- int temp=a[left];
- int k=left;
- while (left<right){
- while(left<right&&a[right]>=temp){
- right--;
- }
- while(left<right&&a[left]<=temp){
- left++;
- }
- swap(a,left,right);
- }
- swap(a,k,left);
- return left; //left后走的 right一定是走到了小于等于temp的地方
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(logn);稳定性:不稳定。
①思想:找到一个基准值,默认为left指针,right往左移,left往右移,如果right小于基准,right和left交换;如果left大于基准,left和right交换,循环进行到left<right不满足,基准值放在最后一个left,接着划分区间进行判断,直到区间里只有一个元素结束。
②代码实现:
- public static void quickSort2(int[] a){
- quickChild2(a,0,a.length-1);
- }
- public static void quickChild2(int[] a,int left,int right){
- if(left>=right){
- return;
- }
- int index=index2(a,left,right);
- quickChild2(a,left,index-1);
- quickChild2(a,index+1,right);
- }
- public static int index2(int[] a,int left,int right){
- int temp=a[left];
- while(left<right){
- while(left<right&&a[right]>=temp){
- right--;
- }
- swap(a,left,right);
- while(left<right&&a[left]<=temp){
- left++;
- }
- swap(a,left,right);
- }
- a[left]=temp;
- return left;
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(logn);稳定性:不稳定。
①思想:前指针pre为left,后指针cur为前指针+1,当cur<=right时,若指针left的值大于指针cur的值,且++pre指针的值不等于cur,交换cur与pre的值,否则不交换;cur++;循环结束后交换left与pre的值。 ----琢磨
②代码实现:
- public static void quickSort3(int[] a){
- quickChild3(a,0,a.length-1);
- }
- public static void quickChild3(int[] a,int left,int right){
- if(left>=right){
- return;
- }
- int index=index3(a,left,right);
- quickChild3(a,left,index-1);
- quickChild3(a,index+1,right);
- }
- public static int index3(int[] a,int left,int right){
- int pre=left;
- int cur=pre+1;
- while(cur<=right){
- if(a[left]>a[cur]&&a[++pre]!=a[cur]){
- swap(a,pre,cur);
- }
- cur++;
- }
- swap(a,left,pre);
- return pre;
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(logn);稳定性:不稳定。
①思想:长度如果小于等于5采用直接插入排序;基准值不再默认为left的值,选择left、right、mid三者的中间值。
②代码实现:
- public static void quickSort4(int[] a){
- int size=a.length;
- if(size<=5){
- insertSort(a);
- }else{
- quickChild4(a,0,size-1);
- }
- }
- public static void quickChild4(int[] a,int left,int right){
- if(left>=right){
- return;
- }
- int mid=findMid(a,left,right);
- swap(a,mid,left); //改变基准值
- int index=index4(a,left,right);
- quickChild4(a,left,index-1);
- quickChild4(a,index+1,right);
- }
- public static int index4(int[] a,int left,int right){
- int temp=a[left];
- while(left<right){
- while(left<right&&a[right]>=temp){
- right--;
- }
- swap(a,left,right);
- while(left<right&&a[left]<=temp){
- left++;
- }
- swap(a,left,right);
- }
- a[left]=temp;
- return left;
- }
- public static int findMid(int[] a,int left,int right){
- int mid=(left+right)/2;
- if(a[left]>a[right]){
- if(a[mid]<a[right]){
- return right;
- }else if(a[mid]>a[left]){
- return left;
- }else {
- return mid;
- }
- }else{
- if(a[mid]<a[left]){
- return left;
- }else if(a[mid]>a[right]){
- return right;
- }else {
- return mid;
- }
- }
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(logn);稳定性:不稳定。
①思想:和双指针思想一样,只是此时将left和right的值放进了队列中,只要队列不为空,再拿出来进行交换并获取下标。
②代码实现:
- public static void quickSort5(int[] a){
- int right=a.length-1;
- int left=0;
- if(right-left>1){
- quickChild5(a,left,right);
- }
- }
- public static void quickChild5(int[] a,int left,int right){
- Queue<Integer> queue=new LinkedList<>();
- queue.offer(left);
- queue.offer(right);
- while (!queue.isEmpty()){
- int start=queue.poll();
- int end=queue.poll();
- int index=index(a,start,end);
- if(index-1>start){
- queue.offer(start);
- queue.offer(index-1);
- }
- if(right>index+1){
- queue.offer(index+1);
- queue.offer(right);
- }
- }
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(logn);稳定性:不稳定。
①思想:不断划分区间,直到区间内只有一个元素时结束,然后在区间内进行排序(类似于双指针中的滑动窗口,指针指的数谁小,数往前放,指针后移)合并。
②代码实现:
- public static void mergeSort(int[] a){
- mergeChild(a,0,a.length-1);
- }
- public static void mergeChild(int[] a,int left,int right){
- if(left>=right){
- return;
- }
- int mid=(left+right)/2;
- mergeChild(a,left,mid); //左边拆分
- mergeChild(a,mid+1,right); //右边拆分
- merge(a,left,mid,right); //合并
- }
- public static void merge(int[] a,int left,int mid,int right){
- int s1=left;
- int e1=mid;
- int s2=mid+1;
- int e2=right;
- int[] temp=new int[right-left+1];
- int k=0;
- while(s1<=e1&&s2<=e2){
- if(a[s1]<a[s2]){
- temp[k++]=a[s1++];
- }else {
- temp[k++]=a[s2++];
- }
- }
- if(s1>e1){
- while(s2<=e2){
- temp[k++]=a[s2++];
- }
- }else {
- while(s1<=e1){
- temp[k++]=a[s1++];
- }
- }
- for(int i=0;i<temp.length;i++){
- a[i+left]=temp[i]; //a是从left开始的 temp是从0开始的
- }
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(n);稳定性:稳定。
①思想:每次直接求出left,right,mid,然后调用方法进行排序。left根据分组元素求出,mid=left+group-1,right=mid+group。
②代码实现:
- public static void mergeSort2(int[] a){
- int group=1; //区间内元素个数:group+1
- int size=a.length;
- while(group<size){
- for(int i=0;i<size;i+=group*2) { //left值
- int left=i;
- int mid=left+group-1;
- if(mid>size-1){ //区间里元素个数不够凑成一个group 可能出现mid越界
- mid=size-1;
- }
- int right=mid+group;
- if(right>size-1){
- right=size-1;
- }
- merge(a,left,mid,right); //进行合并
- }
- group*=2;
- }
- }
③特性:
时间复杂度:O(n*logn);空间复杂度:O(n);稳定性:稳定。
①思想:统计每个数据出现的次数,并对应下标按照顺序存储,按照顺序再放入排序数组。
②代码实现:
- public static void countSort(int[] a){
- int size=a.length;
- int min=a[0];
- int max=a[0];
- for(int i=0;i<size;i++){
- if(a[i]>max){
- max=a[i];
- }else if(a[i]<min){
- min=a[i];
- }
- }
- int[] count=new int[max-min+1];
- for(int i=0;i<size;i++){
- count[a[i]-min]++;
- }
- int j=0;
- for(int i=0;i<count.length;i++){
- while (count[i]>0){
- a[j++]=i+min;
- count[i]--;
- }
- }
- }
③特性:
时间复杂度:O(n);空间复杂度:O(范围);稳定性:稳定
①思想:
①思想:
个位数排序:
十位数排序:
百位数排序:
此时就已经有序了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。