1. 程式人生 > >自己整理的幾種常見排序演算法,及時間複雜度空間複雜度。c++程式設計

自己整理的幾種常見排序演算法,及時間複雜度空間複雜度。c++程式設計

/*****************************************************
copyright (C), 2014-2015, Lighting Studio. Co.,     Ltd. 
File name:
Author:fhb    Version:0.1    Date: 
Description:
Funcion List: 
*****************************************************/


#include <iostream>
#include <cstring>
#include<iomanip>
using namespace std;


template<class T>
void print(T keys[],int n)//輸出字串 
{
for(int i = 0;i<n;i++)
{
cout<<setw(3)<<keys[i]<<" ";
}
cout<<endl;
}
/****************************************************************
直接插入排序:
第i次將a[i]插入到前面a[0]~a[i-1]的子序列中
時間複雜度:平均O(N^2),最好O(N),最壞O(N^2)
空間複雜度O(1),演算法穩定
***************************************************************/
template<class T>
void insertSort(T keys[],int n)
{
for(int i = 1;i < n;i++)
{
T temp = keys[i];
int j;
for(j = i-1;j >=0&&temp<keys[j];j--)//若換成temp<=keys[j],遇到相同的數會多交換一次 
{
keys[j+1] = keys[j];
}
keys[j+1] = temp;
cout<<"第"<<i<<"次 temp="<<temp<<"\t";
print(keys,n);
}
}




/****************************************************************************
折半排序(二分插入排序):
類似於直接插入排序,第i次將a[i]以二分查詢的方法找到位置插入到前面的子序列中
時間複雜度:平均O(N^2),最好O(N),最壞O(N^2)
空間複雜度:O(1) 演算法穩定 
******************************************************************************/
template<class T>
void half_sort(T keys[],int n) 
{  
    int i,j,low,mid,high; 
T temp;   
    for(i=1;i<n;i++)         //最開始第一個元素仍然被看作已經排好的部分  
    {  
        low=0;                 //最低位置  
        temp=keys[i];             //要插入的元素,已經排好序的最高位的下一位元素              
        high=i-1;              //最高位置  
        while(low<=high)          
        {  
            mid=(low+high)/2;   //折中,取中間位置  
            if(keys[mid]>temp)   //判斷要插入的元素和中間元素的大小  
                high=mid-1;     //中間元素大,最高位置取當前中間位置的前一位,重新再求中間位置  
            else  
                low=mid+1;      //中間元素小,最高位置取當前中間位置的後一位,重新再求中間位置  
        } 
        cout<<"high="<<setw(2)<<high<<" low="<<setw(2)<<low<<"  ";     //檢視每次尋找到位置後的高位和低位的位置  
        for(j=i-1;j>high;j--)   //將(high+1)~i的所有元素後移一位  
            keys[j+1]=keys[j];        
        keys[high+1]=temp;        //插入元素  
        print(keys,n);
    }  
}  


/******************************************************************************
shell排序(希爾排序):
將資料分成若干組,每組相隔一段距離,在一組內用直接插入排序,後每次距離減半至1
時間複雜度平均O(N^1.3),最好O(N),最壞O(N^2)
空間複雜度O(1),演算法不穩定
********************************************************************************/
template<class T>
void shellSort(T keys[],int n)
{
for(int delta = n/2;delta>0;delta/=2)//若干次,控制增量每次減半
{
for(int i = delta;i < n;i++)//1次若干組,每組直接插入排序 
{
T temp = keys[i];//當前待插元素 
int j;
for(j = i-delta;j>=0&&temp<keys[j];j-=delta)
{
keys[j+delta] = keys[j];
}
keys[j+delta] = temp;
}
cout<<"delta = "<<delta<<"       ";
print(keys,n);

 } 


/****************************************************************************** 
氣泡排序:
。。。。。。。。。
時間複雜度:平均O(N^2),最好O(N),最壞O(N^2)
空間複雜度O(1),演算法穩定
*********************************************************************************/
template<class T>
void  bubbleSort(T keys[],int n)
{
bool exchange = true;//交換標誌 
for(int i = 1;i < n&&exchange;i++)//如果上次沒有交換過資料,則停止 
{
exchange = false;
for(int j = 0;j<n-1;j++)
{
if(keys[j]>keys[j+1])
{
T temp = keys[j];
keys[j] = keys[j+1];
keys[j+1] = temp;
exchange = true; 
}
}
cout<<"第"<<i<<"次:         ";
print(keys,n);
}
}


/************************************************************************* 
快速排序:
在序列中選擇一個值作基準,小於基準的元素換到序列前,大於的換到序列後,
再對子序列分別再進行快速排序
時間複雜度:平均O(N*lgN),最好O(N*lgN),最壞O(N^2)
空間複雜度:O(lgN),演算法不穩定(?)
*****************************************************************************/
template<class T> 
void quickSort(T keys[],int n,int begin,int end)
{
if(begin>=0&&begin<n&&end>=0&&end<=n&&begin<end)//序列有效
{
int i = begin,j = end;
T vot= keys[i];
while(i != j)
{
while(i<j&&vot<=keys[j])
{
j--;
}
if(i<j)
{
keys[i++]=keys[j];
}
while(i<j&&keys[i]<=vot)
{
i++;
}
if(i<j)
{
keys[j--]=keys[i];
}
}
keys[i] = vot;
cout<<begin<<".."<<end<<",vot="<<vot<<",    ";
print(keys,n);
quickSort(keys,n,begin,j-1);
quickSort(keys,n,i+1,end);

}
template<class T>
void quickSort(T keys[],int n)
{
quickSort(keys,n,0,n-1);
}


/********************************************************************** 
直接選擇排序:
第i次從後n-i個元素序列中選擇最小的元素放到第i個位置
時間複雜度:平均O(N^2),最好O(N^2),最壞O(N^2)
空間複雜度:O(1),演算法不穩定
***********************************************************************8*/
template<class T>
void selectSort(T keys[],int n)
{
for(int i=0;i<n-1;i++)
{
int min = i;
for(int j = i+1;j<n;j++)
{
if(keys[j]<keys[min])
{
min = j;
}
}
if(min!=i)
{
T temp = keys[i];
keys[i] = keys[min];
keys[min] = temp;
}
cout<<"第"<<i+1<<"次 min="<<min<<",\t";
print(keys,n);
}
}




/******************************************************************************** 
堆排序:
1、將一個數據序列建成最小堆,根節點值最小
2、選擇排序,每次將最小值交換到後面,再將其餘值調整成堆,直到子序列長度為1
時間複雜度:平均O(N*lgN),最好O(N*lgN),最壞O(N*lgN)
空間複雜度:O(1),演算法不穩定
*********************************************************************************/
template<class T>
void sift_minheap(T keys[],int n,int begin,int end)
{
int parent = begin,child = 2*parent+1;
T value = keys[parent];
while(child<=end)
{
if(child<end&&keys[child]>keys[child+1])
child++;
if(value>keys[child])
{
keys[parent] = keys[child];
parent = child;
child = 2*parent+1;
}
else
break;
}
keys[parent] = value;
cout<<"sift  "<<begin<<".."<<end<<"      ";
print(keys,n);
}


template<class T>
void heapSort_down(T keys[],int n)
{
for(int i=n/2-1;i>=0;i--)
sift_minheap(keys,n,i,n-1);
for(int i = n-1;i > 0;i--)
{
T temp = keys[0];
keys[0] = keys[i];
keys[i] = temp;
sift_minheap(keys,n,0,i-1);
}
}




/************************************************************************************ 
歸併排序:
將n個長度為1的排序子序列,反覆將相鄰的子序列歸併成一個排序的子序列,知道合併成1個序列;
時間複雜度:平均O(N*lgN),最好O(N*lgN),最壞O(N*lgN);
空間複雜度:O(N),演算法穩定;
***************************************************************************************/
template<class T>
void merge(T X[],int len,T Y[],int begin1,int begin2,int n)
{
int i = begin1,j = begin2,k = begin1;
while(i<begin1+n&&j<begin2+n&&j<len)
{
if(X[i] < X[j])
{
Y[k++] = X[i++];
}
else
{
Y[k++] = X[j++];
}
}
while(i<begin1+n&&i<len)
{
Y[k++] = X[i++];
}
while(j<begin2+n&&j<len)
{
Y[k++] = X[j++];
}
}


template<class T>
void mergepass(T X[],int len,T Y[],int n)
{
cout<<"子序列長度n="<<n<<"   ";
for(int i = 0;i<len;i+=2*n)
{
merge(X,len,Y,i,i+n,n);
}
print(Y,len);
}


template<class T>
void mergeSort(T X[],int len)
{
T *Y = new T[len];
int n = 1;
while(n < len)
{
mergepass(X,len,Y,n);
n*=2;
if(n<len)
{
mergepass(Y,len,X,n);
n*=2;
}
}
}


//主函式 
int main()
{
int keys[]={32,26,87,72,26,17};
cout<<"關鍵字序列:    ";
print(keys,6);
//insertSort(keys,6);
//half_sort(keys,6);
//shellSort(keys,6);
//quickSort(keys,6);
//bubbleSort(keys,6);
//selectSort(keys,6);
//heapSort_down(keys,6);
mergeSort(keys,6);
    return 0;
}