数据结构 --- 排序算法(1)

这里都是按照升序排序的;
交换函数如下:

void Swap(int *a ,int *b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
    return;
}
1.冒泡排序

方法一:首先,常规冒泡算法,外循环定义count 为排序的趟数,内循环为每趟进行比较并且交换,实现代码如下:

void BubbleSort(int array[],size_t size){
    if(size <= 1){
        return;
    }
    size_t count = 0;
    for(;count < size - 1;count++){
        size_t i = 0;
        for(i = 0;i < size - count -1;i++){
            if(array[i] > array[i+1]){
                Swap(&array[i],&array[i+1]);
            }
        }
    }//for(;count < size - 1;count++)
    return;
}

方法二:定义一个边界bound,并且[0,bound)为有序区间,[bound,size)为待排序区间,代码实现如下:

void BubbleSort2(int array[],size_t size){
    if(size <= 1){
        return;
    }
    //[0,bound)为一个有序区间
    //[bound,size)为待排序区间
    size_t bound = 0;
    for(;bound < size;bound++){
        size_t cur = size - 1;
        for(;cur > bound;cur--){
            if(array[cur] < array[cur - 1]){
                Swap(&array[cur],&array[cur - 1]);
            }
        }
    }
    return;
}

冒泡排序的时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定排序算法

2.选择排序

思路:整体思路为打擂台,定义第一个元素为擂主即bound,然后让bound之后每一个元素与bound进行比较,如果bound大于后面的元素就进行交换(升序排序);
代码实现如下:

void SelectSort(int array[],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(array[cur] < array[bound]){
                Swap(&array[cur],&array[bound]);
            }
        }
    }
    return;
}

选择排序时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:不稳定

3.插入排序

思路:定义一个边界bound,[0,bound)为有序区间,将这个有序区间看成线性表,
[bound,size)为待排序区间,在定义一个cur从后往前开始一边进行比较一边进行搬运,将bound_value的值插入到线性表的合适位置,这里需要注意的是,在搬运之前,先将bound的值保存起来,避免搬运之后将其覆盖;
代码实现如下:

void InsertSort(int array[],size_t size){
    if(size <= 1){
        return;
    }
    size_t bound = 1;
    for(;bound < size;bound++){
        int bound_value = array[bound];
        size_t cur = bound;
        for(;cur > 0;cur--){
            if(bound_value < array[cur - 1]){
                array[cur] = array[cur -1];
            }else{
                //说明已经找到一个合适的位置
                break;
            }
        }//for(;cur > 0;cur--)
        array[cur] = bound_value;
    }
    return;
}

插入排序的时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定的排序算法
特点:
1.数组元素个数比较小的时候,执行效率比较快
2.如果数组基本有序,执行效率也很快

4.堆排序

思路:整体思路为两步
(1).根据数组建立堆(如果是升序排序,建立大堆);
有两种建立堆的方法:下沉式调整和上浮式调整;
这里两种方法都有实现,具体看代码
(2).循环的删除堆顶元素,删除完之后,排序也就完成了;
先将堆顶元素与最后一个元素进行交换,然后调用下沉式调整进行调整,使仍然符合堆的要求;
代码实现:
代码解释:从HeapSort函数开始;

void AdjustUp(int array[],size_t size,size_t index){
    (void)size;
    size_t child = index;
    size_t parent = (child - 1)/2;
    while(child > 0){
        if(array[parent] < array[child]){
            Swap(&array[parent],&array[child]);
        }else{
            break;
        }
        child = parent;
        parent = (child - 1)/2;
    }
    return;
}
void AdjustDown(int array[],size_t size,size_t index){
    size_t parent = index;
    size_t child = 2 * parent + 1;
    while(child < size){
        if(child + 1 < size && array[child] < array[child + 1]){
            child = child + 1;
        }
        if(array[parent] < array[child]){
            Swap(&array[parent],&array[child]);
        }
        parent = child;
        child = 2 * parent + 1;
    }
    return;
}
void HeapCreate(int array[],size_t size){
    if(size <= 1){
        return;
    }
#if 1
    //下沉式调整
    size_t i = (size - 1 -1)/2;
    for(;i > 0;i--){
        AdjustDown(array,size,i);
    }
    AdjustDown(array,size,0);
#else
    //上浮式调整
    size_t bound = 0;
    for(;bound < size;bound++){
        AdjustUp(array,bound,bound);
    }
#endif
    return;
}
void HeapPop(int array[],size_t heap_size){
    if(heap_size <= 1){
        return;
    }
    Swap(&array[0],&array[heap_size - 1]);
    AdjustDown(array,heap_size - 1,0);
    return;
}
void HeapSort(int array[],size_t size){
    if(size <= 1){
        return;
    }
    //1.基于数组建立一个堆(如果是升序排序,建立大堆)
    HeapCreate(array,size);
    //2.循环的删除堆顶元素,将所有的堆顶元素都删除完了,排序完成
    size_t i = 0;
    for(;i < size - 1;i++){
        //第二个参数表示数组中那部分区间是符合堆的规则
        HeapPop(array,size - i);
    }
    return;
}

堆排序时间复杂度:O(N*logN)
空间复杂度:O(1)
稳定性:不稳定排序

猜你喜欢

转载自blog.csdn.net/liru_1996/article/details/80482181