算法时间复杂度以及代码实现

来源:互联网 发布:mac上如何打开rar文件 编辑:程序博客网 时间:2024/06/03 09:09

1 插入的时间复杂度

附:选择排序:思想为从所有序列中找最小的放第一个位置,之后从剩余的元素中找最小的放第二个位置,直到所有的。时间复杂度为O(n*n)

折半插入排序(二分插入排序):在直接插入排序的基础上,对插入A[i]进行了修改,直接插入排序是从后向前比较,而折半插入排序为直接从A[i-1/2]那个位置进行比较,大了在[i-1/2]-A[i-1]查找,否则在A[0]-A[i-1/2]找,比直接插入减少了比较次数,单是元素移动次数不变,所以,时间复杂度仍为O(n^2)。


2 查找的时间复杂度

2.1  二分查找

二分查找又称折半查找,优点是查找速度快,平均性能好,缺点是待查表为有序表,且插入、删除困难。
适用于:不经常变动而查找频繁的有序列表。
根据比较中间关键字来查找需要查找的关键字。
二分查找法的时间复杂度是O(log(n)),最坏情况下为O(n)

3代码实现

3.1 冒泡排序

package sort;
/*
 比较相邻的元素,如果第一个比第二个大,则交换他们两个,依次类推
 平均O(n*2) 最坏O(n*2),最好O(n) 空间O(1) 稳定,简单
 
 输出为:
 排序前为:1  4  6  2  3  7  9  5  10  0  
排序后为:0  1  2  3  4  5  6  7  9  10  
 * */
public class BubbleSort {
    public static void bubbleSort(int[] numbers){
        int length=numbers.length;
        int j,temp;
        System.out.print("排序前为:");
        for(j=0;j<length;j++){
            System.out.print(numbers[j]+"  ");
        }
        System.out.println();
        for(int i=0;i<length-1;i++){
            for(j=0;j<length-1-i;j++){
                if(numbers[j]>numbers[j+1]){
                    temp=numbers[j];
                    numbers[j]=numbers[j+1];
                    numbers[j+1]=temp;
                }    
            }    
        }
        System.out.print("排序后为:");
        for(j=0;j<length;j++){
            System.out.print(numbers[j]+"  ");
        }    
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] numbers={1,4,6,2,3,7,9,5,10,0};
        bubbleSort(numbers);    
    }
}

3.2 快速排序

下面为数组输出函数

    public static void printArray(int[] num){
        for(int i=0;i<num.length;i++){
            System.out.print(num[i]+"  ");
        }
    }    

/*
快速排序(平均为:O(nlogn),最坏为O(n*n) ,最好为O(nlogn),空间为O(nlogn),不稳定,较复杂)
从数列中挑出一个元素,称为基准,重新排列数列,所有比基准小的放到基准之前,所有比基准大的放到基准后面,之后递归的进行排列    

输出为:
基准为:4排序后为:-4  0  2  1  3  4  9  5  10  7  11  6  
基准为:-4排序后为:-4  0  2  1  
基准为:0排序后为:0  2  1  
基准为:2排序后为:1  2  
基准为:9排序后为:6  5  7  9  11  10  
基准为:6排序后为:5  6  
基准为:11排序后为:10  11  
结果为:
快速排序原先数组为:
4  6  2  1  3  7  9  5  10  0  11  -4  12  
快速排序结果为:
-4  0  1  2  3  4  5  6  7  9  10  11  12  

*
*/
    public static void quickSort(int[] numbers,int start,int end){
        int cir=0;
        int base=numbers[start];    
        if(start<end){
        int i=start,j=end;
        while(i<j){
            while(i<j&&numbers[j]>base)
                j--;
            numbers[i]=numbers[j];
            while(i<j&&numbers[i]<base)
                i++;
            numbers[j]=numbers[i];
        }
        numbers[i]=base;
        
        /*System.out.print("基准为:"+base+"排序后为:");
        
        for(cir=start;cir<end;cir++){
            System.out.print(numbers[cir]+"  ");
        }
        System.out.println("");
        */
        
        quickSort(numbers,start,i-1);
        quickSort(numbers,i+1,end);        
        }
        
    }


主方法调用为:
/*快速排序  start*/
        int[] numbers={4,6,2,1,3,7,9,5,10,0,11,-4,12};
        System.out.println("快速排序原先数组为:");
        printArray(numbers);
        quickSort(numbers,0,numbers.length-1);
        System.out.println("\n快速排序结果为:");
        printArray(numbers);//*****因为numbers为数组类型,调用函数交换为其内部的值已经发生改变,只需输出即可
        /*快速排序   end*/

3.3 选择排序

/*
 选择排序-平均-最坏-最好,均为O(n*n),
 在未排序中找到最小的放在起始位置,再从剩余未排序的找出最小元素,依次类推
 
输出为:
选择排序原先数组为:
4  6  2  1  3  7  9  5  10  0  11  -4  12  
选择排序结果为:
-4  0  1  2  3  4  5  6  7  9  10  11  12  
 */    
public static void selectSort(int[] num){
    
    int length=num.length;
    int i,j,min = 0;
    for(i=0;i<length-1;i++){
        min=i;
        for(j=i+1;j<length;j++){
            if(num[min]>num[j]){
                min=j;
            }
        }
        if(min==i){  //第一个为最小的元素,无需交换
            //System.out.println();
            //System.out.println(" 第"+(i+1)+"无需移动,值为: "+num[i]);
            
        }else{ //需要交换
            
            //System.out.println();
            //System.out.println(" 第"+(i+1)+"与第"+(min+1)+"个交换,值分别为 "+num[i]+"和"+num[min]);
            int temp=num[i];
            num[i]=num[min];
            num[min]=temp;            
        }
    }
}
   
主方法调用为:

    /*选择排序  start*/
        int[] numbers2={4,6,2,1,3,7,9,5,10,0,11,-4,12};
        System.out.println("\n\n选择排序原先数组为:");
        printArray(numbers2);
        selectSort(numbers2);
        System.out.println("\n选择排序结果为:");
        printArray(numbers2);
        /*选择排序  end*/

3.4 插入排序

/*
插入排序:平均为O(n*n),最坏O(n*n),最好O(n),空间为O(1),稳定,简单
1.从第一个元素开始,该元素已经被认为排好序了
2.取下一个元素,在已经排好序的元素中,从后向前排
3.如果该元素大于新元素,将该元素移到下一个位置
4.重复步骤3,直到找到已排好序的元素小于或者等于新元素的位置
5.将新元素插入到该位置
6.重复步骤2
输出为:
插入排序原先数组为:
4  6  2  1  3  7  9  5  10  0  11  -4  12  
插入排序结果为:
-4  0  1  2  3  4  5  6  7  9  10  11  12  
*/
public static void insertSort(int[] num){
     int length=num.length;
     int temp,j;
     for(int i=1;i<length;i++){
         temp=num[i];//新的元素
         for(j=i;j>0&&temp<num[j-1];j--){
                 num[j]=num[j-1];
         }
         num[j]=temp;
     }
}

主方法调用:

/*插入排序  start*/
        int[] numbers3={4,6,2,1,3,7,9,5,10,0,11,-4,12};
        System.out.println("\n\n插入排序原先数组为:");
        printArray(numbers3);
        insertSort(numbers3);
        System.out.println("\n插入排序结果为:");
        printArray(numbers3);
        /*插入排序  end*/

3.5 希尔排序


/*
希尔排序:平均为O(nlogn),最坏O(nlogn),最好无,空间为O(1),不稳定,较复杂
概念:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
步骤:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量
    =1(<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
*****一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
实例:
希尔排序原先数组为:
16  4  6  2  1  3  7  9  5  10  0  11  -4  15  
希尔排序结果为:
-4  0  1  2  3  4  5  6  7  9  10  11  15  16  
*/

    public static void shellSort(int[] num) {
        int length=num.length,j;
        for(int increase=length/2;increase>=1;increase/=2){        
            //System.out.println("increase="+increase);    
            for(int i=increase;i<length;i++){  //下面为插入排序
                int temp=num[i];
                //System.out.println("temp="+temp+"  num["+i+"]="+num[i]);
                for(j=i;j>=increase&&temp<num[j-increase];j-=increase){    
                    //System.out.println("num["+j+"]="+num[j]+"num["+(j-increase)+"]="+num[(j-increase)]+"  increase="+increase);        
                    num[j]=num[j-increase];
                }
                num[j]=temp;
                //System.out.println(" num["+j+"]="+num[j]);
            }
        }
    }
    主方法调用:

/*希尔排序  start*/
        int[] numbers4={16,4,6,2,1,3,7,9,5,10,0,11,-4,15};
        System.out.println("\n\n希尔排序原先数组为:");
        printArray(numbers4);
        shellSort(numbers4);
        System.out.println("\n希尔排序结果为:");
        printArray(numbers4);
        /*希尔排序  end*/

3.6 归并排序

   
/*
归并排序:平均为O(nlogn),最坏O(nlogn),最好O(nlogn),空间O(n),稳定,较复杂
将一个数组分为2个,2个分为4个,一直到只有1个元素,后再开始合并元素,4合为2,2合为1,即可。
实例:
归并排序原先数组为:
16  4  6  2  1  3  7  9  5  10  0  11  -4  15  
归并排序结果为:
-4  0  1  2  3  4  5  6  7  9  10  11  15  16  
*/    
    
    public static void merge(int[] num,int low,int mid,int high){
        int[] num1=new int[high-low+1]; //重新开辟空间,此时num1从0开始
        //合并num[low..mid]与num[mid+1..high]为num[low..high]
        int i,j,k=0;  //注意k是从0开始
        for(i=low,j=mid+1;i<=mid&&j<=high;k++){
            if(num[ i]<num[j]){
                num1[k]=num[i];
                i++;
            }else{
                num1[k]=num[j];
                j++;
            }    
        }
        if(i<=mid){ //前半段剩下的复制到num1数组中
            for(;i<=mid;i++,k++){
                num1[k]=num[i];
            }
        }
        if(j<=high){ //后半段剩下的复制到num1数组中
            for(;j<=high;j++,k++){
              num1[k]=num[j];    
            }
        }
        for(i=low,k=0;i<=high;i++,k++){
            num[i]=num1[k];
        }
    }
    public static void MergSort(int[] num,int low,int high){ //将num[low..high]归并排序到num1[low..high]
        
        if(low==high){ //无需交换
            
        }else{ //归并开始排序
         int mid=(low+high)/2;
         MergSort(num,low,mid);
         MergSort(num,mid+1,high);
         merge(num,low,mid,high);      
        }    
    }

主方法调用:

    /*归并排序  start*/
        int[] numbers5={16,4,6,2,1,3,7,9,5,10,0,11,-4,15};
        System.out.println("\n\n归并排序原先数组为:");
        printArray(numbers5);
        MergSort(numbers5,0,numbers5.length-1);
        System.out.println("\n归并排序结果为:");
        printArray(numbers5);
        /*归并排序  end*/

       

3.7 堆排序

/*
堆排序:最好最坏平均均为O(nlogn),空间为O(1),不稳定,较复杂
整个过程为建堆和交换的过程,从第一个非叶子节点开始,比较节点和它的左右子节点,保证最大的为根节点
实例:

堆排序原先数组为:
16  4  6  2  1  3  7  9  5  10  0  11  -4  15  
堆排序结果为:
-4  0  1  2  3  4  5  6  7  9  10  11  15  16  
*/    

    public static void heapSort(int[] array){
    
        buildHeap(array);
        int n=array.length;
        int i=0;
        for(i=n-1;i>0;i--){
          swap(array,0,i);    
          heapify(array,0,i-1); //注意**********调整时,不算已经排好序的最后一个
        }
    }
    public static void buildHeap(int[] array){//构建堆
    
        int n=array.length;
        for(int i=n/2-1;i>=0;i--){
           heapify(array,i,n-1);//调整堆,其中n-1为最大的边界值,即最后一个数字    
        }
    }
    public static void heapify(int[] num,int index,int max){
        int left=2*index+1;
        int right=2*index+2;
        int largest=0;
        
        
        if(left<=max&&num[left]>num[index]){ //注意顺序***left<=max与num[left]>num[index]
            largest=left;
        }else{
            largest=index;
        }    
        if(right<=max&&num[largest]<num[right]){  //
            largest=right;
        }
        if(largest!=index){
            swap(num,largest,index);
            heapify(num,largest,max);
        }    
    }
    
    public static void swap(int[] array,int i,int j){
        int temp=array[i];
        array[i]=array[j];
        array[j]=temp;
    }
   

主方法调用:

    /*堆排序  start*/
        int[] numbers6={16,4,6,2,1,3,7,9,5,10,0,11,-4,15};
        System.out.println("\n\n堆排序原先数组为:");
        printArray(numbers6);
        heapSort(numbers6);
        System.out.println("\n堆排序结果为:");
        printArray(numbers6);
        /*堆排序  end*/




1 0