简单排序

简单排序之冒泡排序、选择排序、堆排序、插入排序。

冒泡排序算法的原理如下:

  1. 比较相邻的元素,如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

选择排序算法的原理如下:
  对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较如果后面的元素比他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。

大根堆排序的基本思想如下:

  1. 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
  2. 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
  3. 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
    ……
    直到无序区只有一个元素为止。

直接插入排序的算法原理如下:

  1. 设置监视哨r[0],将待插入记录的值赋值给r[0];
  2. 设置开始查找的位置j;
  3. 在数组中进行搜索,搜索中将第j个记录后移,直至r[0].key≥r[j].key为止;
  4. 将r[0]插入r[j+1]的位置上。
#include <stdio.h>

/////////////////////////////////////////////
//冒泡排序
//时间复杂度:O(N^2)
//空间复杂度:O(1)
///////////////////////////////////////////
//[0,bound]是有序区间
//[bound,size]是待排序区间
void Swap(int* a,int* b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}
void BubbleSort(int array[],size_t size){
    if(size <= 1){
        return;
    }
    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)
////////////////////////////////////////////////
//
void SelectSort(int array[],size_t size){
    if(size <= 1){
        return;
    }
    size_t bound = 0;
    for(;bound < size;++bound){
        size_t i = bound;
        for(;i < size;++i){
            if(array[bound] > array [i]){
                Swap(&array[bound],&array[i]);
            }
        }
    }
    return;
}

//////////////////////////////////////////////////
//堆排序
//时间复杂度:O(N*logN)
//空间复杂度:O(1)
/////////////////////////////////////////////////
//要求从小到大排序,所以应该建立一个大堆
void AdjustDown(int array[],size_t size ,size_t index){
    size_t parent = index;
    size_t child = 2 * parent + 1;
    while(child < size){
        //1.比较左右子树
        if(child+1 < size && array[child+1] > array[child]){
            child = child + 1;
        }
        //2.比较child 和 parent
        if(array[child] > array[parent]){
            Swap(&array[child],&array[parent]);
        }
        else{
            break;
        }
        parent = child;
        child = 2*parent + 1;
    }
    return;
}
void HeapCreate(int array[],size_t size){
    //算出最后一个元素的父节点
    size_t i = (size - 1 - 1) / 2;
    for(;i > 0;--i){
        AdjustDown(array,size,i);
    }
    AdjustDown(array,size,0);
}

void HeapSort(int array[],size_t size){
    if(size <= 1){
        return;
    }
    //1.先建立一个堆
    HeapCreate(array,size);
    //2.依次删除堆顶元素
    size_t heap_size = size;
    while(heap_size > 0){
        Swap(&array[0],&array[heap_size - 1]);
        --heap_size;
        AdjustDown(array,heap_size,0);
    }
    return;
}

////////////////////////////////////////////////////////
//插入排序
//时间复杂度:O(N^2)
//空间复杂度:O(1)
///////////////////////////////////////////////////////
void InsertSort(int array[],size_t size){
    if(size <= 1){
        return;
    }
    size_t bound = 1;
    for(;bound < size; ++bound){
        int value = array[bound];
        size_t i = bound;
        for(;i > 0;--i){
            if(array[i - 1] > value){
                //进行搬运
                array[i] = array[i - 1];
            }
            else{
                break;
            }
        }
        //无论上面循环是通过i == 0方式退出的
        //还是找到一个合适的位置退出的,下面逻辑都合法
        array[i] = value;
    }
    return;
}

void Print(int array[],size_t size){
    size_t i = 0;
    for(;i < size;++i){
        printf("%d ",array[i]);
    }
}

int main(){
    int array[] = {1,3,12,45,13,65,23,19,34};
    size_t len = sizeof(array)/sizeof(array[0]);

    BubbleSort(array,len);
    printf("[冒泡排序后]:");
    Print(array,len);
    printf("\n");

    SelectSort(array,len);
    printf("[选择排序后]:");
    Print(array,len);
    printf("\n");

    HeapSort(array,len);
    printf("[堆排序后]:");
    Print(array,len);
    printf("\n");

    InsertSort(array,len);
    printf("[插入排序后]:");
    Print(array,len);
    printf("\n");

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值