排序算法的实现

  • 冒泡排序

重复的走访过要排序的数列。一次比较两个元素,如果他们的顺序错误,就把他们交换过来。走访数列的工作是重复的进行,直到没有再需要交换的元素,即该序列已经排序完成。

                            

void Swap(int* a,int* b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

void BubbleSort(int arr[],size_t size){
    if(size <= 1)
        return;
    size_t bound = 0;//[0,bound)表示有序元素,[bound,size)表示待排序元素
    for(;bound < size;bound++){
        size_t cur = size-1;
        for(;cur > bound;cur--){
            if(arr[cur] < arr[cur-1])
                Swap(&arr[cur],&arr[cur-1]);
        }
    }
    return;
}
  • 选择排序

每一趟从待排序的数据元素中选出最大或最小的一个元素,顺序放在已经排好序的数列的最后,直到全部待排序的数据元素排完。

                            

void Swap(int* a,int* b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

void SelectSort(int arr[],size_t size){
    if(size <= 1)
        return;
    size_t bound = 0;
    for(;bound < size;bound++){
        size_t cur = bound+1;
        for(;cur < size;cur++){
            if(arr[bound] > arr[cur])
                Swap(&arr[bound],&arr[cur]);
        }
    }
    return;
}
  • 插入排序

有一个已经有序的数据序列,在这个已经排好序的数据序列中插入一个数,要求插入此数后,该数据序列仍然有序。

                                

void InsertSort(int arr[],size_t size){
    if(size <= 1)
        return;
    size_t bound = 1;
    //[0,bound)表示有序元素,[bound,size)表示待排序元素
    //插入排序将前面的有序区间当成一个线性表,然后将bound位置的元素插入到线性表中的合适位置
    for(;bound < size;bound++){
        int bound_value = arr[bound];
        size_t cur = bound;
        for(;cur > 0;cur--){
            if(arr[cur-1] > bound_value)//进行搬运
                arr[cur] = arr[cur-1];
            else//说明已找到合适的位置
                break;
    }
        arr[cur] = bound_value;
    }
}
  • 堆排序

利用堆这种数据结构所设计的一种排序算法,是选择排序的一种。

堆是具有以下性质的完全二叉树:每个节点的值均大于等于其左右孩子结点的值,称为大堆;每个节点的值均小于等于其左右孩子结点的值,称为小堆。

在数组的升序排序中,需要使用的是大堆;在数组的降序排序中,需要使用的是小堆。

堆排序的基本思想是:将待排序序列构成一个大堆(假设升序排序),此时整个序列中的最大值即为堆顶元素的值。将堆顶元素的值与末尾元素的值进行交换,此时末尾元素的值即为最大值。然后将剩余的n-1个元素重新构造成一个堆,这样就会得到n个元素的次小值。如此反复执行,即可得到一个有序序列了。

                                

void AdjustDown(int arr[],size_t size,size_t index){
    size_t parent = index;
    size_t child = 2*parent+1;
    while(child < size){//升序排序,建立大堆
        if(child+1 < size && arr[child+1] > arr[child])
            child += 1;//child指向了左右子树中较大的
        if(arr[parent] < arr[child])
            Swap(&arr[parent],&arr[child]);
        parent = child;
        child = 2*parent+1;
    }
    return;
}


void HeapCreate(int arr[],size_t size){
    if(size <= 1)
        return;
    size_t i = (size-1-1)/2;
    for(;i > 0;i--)
        AdjustDown(arr,size,i);
    AdjustDown(arr,size,0);
    return;
} 


void HeapPop(int arr[],size_t heap_size){
    if(heap_size <= 1)
        return;
    Swap(&arr[0],&arr[heap_size-1]);
    AdjustDown(arr,heap_size-1,0);
    return;
}

void HeapSort(int arr[],size_t size){
    if(size <= 1)
        return;
    HeapCreate(arr,size);//创建堆的函数
    size_t i = 0;
    for(;i < size;i++)
        HeapPop(arr,size-i);
    //size-i表示数组中哪部分区间符合堆的规则
    //即第i次删除前,[0,size-i)都是堆
    return;
}
  • 希尔排序

希尔排序是插入排序的一种,又称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。本质上是一种分组插入的方法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

        (1)插入排序在对几乎已经排好序的数据操作时,效率高;

        (2)插入排序在对元素个数较少的数据操作时,效率高。

                            

void ShellSort(int arr[],int64_t size){
    int64_t gap = size/2;//使用希尔序列
    for(;gap > 0;gap /= 2){//生成步长序列
        int64_t bound = gap;
        for(;bound < size;bound++){//进行插入排序
            int bound_value = arr[bound];
            int64_t cur = bound;
            for(;cur  >= gap;cur -= gap){//线性表的查找和搬运
                //cur-=gap表示找到同组元素中的上一个元素
                if(arr[cur-gap] > bound_value)//进行搬运
                    arr[cur] = arr[cur-gap];
                else//找到了
                    break;
            }
            arr[cur] = bound_value;
        }
    }
    return;
}






猜你喜欢

转载自blog.csdn.net/cecilia3333/article/details/80467628