各种内部排序算法

来源:互联网 发布:大数据时代日语 编辑:程序博客网 时间:2024/06/15 14:24


#include <iostream>

using namespace std;
//各种内部排序算法

//一:插入排序,时间复杂度为O(n*n)
//交还函数
void Swap(int arr[],int i,int j){
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
void insertSort(int arr[],int n){
    for(int i=0;i<n;i++){
        for(int j=i;j>0;j--){
            if(arr[j]<arr[j-1])
                Swap(arr,j,j-1);
            else
                break;
        }
    }
}
//二:冒泡排序,时间复杂度为O(n*n)
void bubbleSort(int arr[],int n){
    for(int i=0;i<n;i++){
        for(int j=n-1;j>i;j--){
            if(arr[j]<arr[j-1])
                Swap(arr,j,j-1);
        }
    }
}

//三:选择排序,时间复杂度为O(n*n)
void selectSort(int arr[],int n){
    for(int i=0;i<n;i++){
        int small = i;
        for(int j=i+1;j<n;j++){
            if(arr[small]>arr[j])
                small = j;
        }
        Swap(arr,i,small);
    }
}
//排序算法为O(n*n)的时间复杂度太大,我们必须找出一些高效的排序算法
//四:希尔排序:增量为2的希尔排序的时间复杂度为O(n的3/2次方),有时很接近O(n)
void shellSort(int arr[],int n){
    //增量为2
    for(int gap = n/2;gap>0;gap=gap/2){
        for(int i=0;i<gap;i++){
            for(int j=gap+i;j<n;j+=gap){
                //对每一个分组排序
                if(arr[j]<arr[j-gap]){//使用插入排序对其排序
                    int tmp = arr[j];
                    int k = j-gap;
                    while(k>=0&&arr[k]>tmp){
                        arr[k+gap] = arr[k];
                        k = k-gap;
                    }
                    arr[k+gap] = tmp;
                }
            }
        }
    }
}

//五:快速排序:平均复杂度O(nlogn),快速排序并不稳定。
//快速排序依赖与基准元素的比较,比较次数远多于移动次数,每一次比较可以确定一个基准值元素的值
/*1.先从数列中取出一个数作为基准数。
  2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
  3.再对左右区间重复第二步,直到各区间只有一个数。*/

//将轴值放到数组的适当位置
int Partition(int arr[],int left,int right){
    int tmp = arr[right];
    int i =left-1;
    for(int j = left;j<right;j++){//在arr[left] 到arr[right-1]中寻找比tmp小的元素与第i++个元素交换
        if(arr[j]<tmp){
            i++;
            if(i!=j)
                Swap(arr,i,j);
        }
    }
    Swap(arr,i+1,right);
    return (i+1);
}

void quickSort(int arr[],int left,int right){
    if(right<=left)
        return;
    int pivot = Partition(arr,left,right);
    quickSort(arr,left,pivot-1);
    quickSort(arr,pivot+1,right);
}

//归并排序:最大,最小,平均复杂度都为:O(n*n)
/*两路归并排序,tmpArr为临时数组,*/

void Merge(int arr[],int p,int q,int r){
    int n1,n2,i,j,k;
    n1 = q-p+1;
    n2 = r-q;
    int left[n1];
    int right[n2];
    for(i=0;i<n1;i++){//对左数组赋值
        left[i] = arr[p+i];
    }
    for(j =0;j<n2;j++){//对右数组赋值
        right[j] = arr[q+1+j];
    }
    i=j=0;
    k=p;
    while(i<n1&&j<n2){//将数组元素值两两比较,并合并到arr数组
        if(left[i] <= right[j])
            arr[k++] = left[i++];
        else
            arr[k++] = right[j++];
    }
    while(i<n1){//如果左数组有元素剩余,则将剩余元素合并到arr数组
        arr[k++] = left[i++];
    }
    while(j<n2){//如果右数组有元素剩余,则将剩余元素合并到arr数组
        arr[k++] = right[j++];
    }
}
void mergeSort(int arr[],int left,int right){
    if(left<right){
        int middle=(left+right)/2;
        mergeSort(arr,left,middle);
        mergeSort(arr,middle+1,right);
        Merge(arr,left,middle,right);
    }
}

//堆排序:最大,最小,平均时间复杂度均为O(nlogn),并不依赖于原始数组的有序程度
class maxHeap{
private:
    int Size; //最大堆的元素数目
    int * Array; //最大堆数组的首地址指针
public:
    maxHeap(int arr[],int n);
    void buildHeap();//构建堆
    void siftDown(int index);//向下筛选
    void Swap(int index1,int index2);//交换位置
    void removeMax();//删除堆顶的最大值并且与数组最后一个元素交换位置重新构建一个最大堆
    int leftChild(int index);//返回做儿子位置
    int rightChild(int index);//返回右儿子位置
};

maxHeap::maxHeap(int arr[],int n){
    this->Array = arr;
    Size = n;
    buildHeap();
}

void maxHeap::buildHeap(){
    for(int i =Size/2-1;i>=0;i--){
        siftDown(i);
    }
}

void maxHeap::siftDown(int index){//关键步骤,调整堆使其成为最大堆
    int max_index = leftChild(index);
    while(max_index<Size){//如果没到底部
        if(max_index <Size-1&&Array[rightChild(index)]>Array[max_index])//如果没到底部并且右额日子比左儿子大
            max_index++;//指向右儿子
        if(Array[index]>Array[max_index])//如果调整完毕
            break;
        Swap(index,max_index);//和左/右儿子交换并调整下标
        index = max_index;
        max_index = leftChild(index);
    }
}

void maxHeap::Swap(int index1,int index2){
    int tmp = Array[index1];
    Array[index1] = Array[index2];
    Array[index2] = tmp;
}

void maxHeap::removeMax(){
    Swap(0,Size-1);
    Size--;
    siftDown(0);
}
int maxHeap::leftChild(int index){
    return index*2+1;
}
int maxHeap::rightChild(int index){
    return index*2+2;
}

void heapSort(int arr[],int n){
    maxHeap max_heap = maxHeap(arr,n);
    //删除最大值(堆顶),即每次将最大值与数组最后一个元素交换位置
    for(int i=0;i<n;i++){
        max_heap.removeMax();
    }
}
//基数排序,时间复杂度为:O(nlog(r)m),r为所采用的基数,m为堆数。
//计算关键字位数的最大值
int keySize(int arr[],int Size){
    int key_size = 1;
    for(int i =0;i<Size;i++){
        int tmp = 1;
        int n =10;
        while(arr[i]/n >0){
            tmp++;
            n*=10;
        }
        key_size = (tmp>key_size)?tmp:key_size;
    }
    return key_size;
}
//基数排序:
void radixSort(int arr[],int Size){
    int bucket[10][10]={0};//定义基数桶
    int order[10] = {0};//保存每个桶之中的元素个数
    int key_size = keySize(arr,Size);
    for(int n=1;key_size>0;n*=10,key_size--){
        //将待排序的元素按照关键值的大小依次放入基数桶中
        for(int i=0;i<Size;i++){
            int lsd =(arr[i]/n)%10;
            bucket[lsd][order[lsd]] = arr[i];
            order[lsd]++;
        }
        //将桶中的元素重新串起来
        int k =0;
        for(int i = 0;i<10;i++){
            if(order[i]!=0){
                for(int j =0;j<order[i];j++){
                    arr[k] = bucket[i][j];
                    k++;
                }
                order[i] = 0;
            }
        }
    }

}
int main()
{
    int arr1[5] = {3,1,2,5,4};
    cout<<"插入排序:"<<endl;
    insertSort(arr1,5);
    for(int i=0;i<5;i++)
        cout<<arr1[i]<<" ";
    cout <<endl;
    int arr2[5] = {3,1,2,5,4};
    cout<<"冒泡排序:"<<endl;
    bubbleSort(arr2,5);
    for(int i=0;i<5;i++)
        cout<<arr2[i]<<" ";
    cout <<endl;
    int arr3[5] = {3,1,2,5,4};
    cout<<"选择排序:"<<endl;
    selectSort(arr3,5);
    for(int i=0;i<5;i++)
        cout<<arr3[i]<<" ";
    cout <<endl;
    cout<<"希尔排序:"<<endl;
    int arr4[8] = {6,8,7,3,1,2,5,4};
    shellSort(arr4,8);
    for(int i=0;i<8;i++)
        cout<<arr4[i]<<" ";
    cout <<endl;
    cout <<"快速排序:"<<endl;
    int arr5[8] = {6,8,7,3,1,2,5,4};
    quickSort(arr5,0,7);
    for(int i=0;i<8;i++)
        cout<<arr5[i]<<" ";
    cout <<endl;
    cout<<"归并排序:"<<endl;
    int arr6[8] = {6,8,7,3,1,2,5,4};
    mergeSort(arr6,0,7);
    for(int i=0;i<8;i++)
        cout<<arr6[i]<<" ";
    cout <<endl;
    cout<<"堆排序:"<<endl;
    int arr7[8] = {6,8,7,3,1,2,5,4};
    heapSort(arr7,8);
    for(int i=0;i<8;i++)
        cout<<arr7[i]<<" ";
    cout <<endl;
    cout<<"基数排序:"<<endl;
    int arr8[10] = {73,22,93,43,55,14,28,65,39,81};
    radixSort(arr8,10);
    for(int i=0;i<10;i++)
        cout<<arr8[i]<<" ";
    cout <<endl;
    return 0;
}

//其中不稳定的排序是:选择,希尔,快排,堆

0 0
原创粉丝点击