C语言_9种排序算法

01 - 冒泡排序

void bubbleSort(int *arr, int len)
{
    if(NULL == arr || len < 2)
    {
        return;
    }

    int i,j;
    for(i = 0; i < len; i++)
    {
        for(j = len - 1 - i; j >= 0; j--)
        {
            if(arr[j-1] > arr[j])
            {
                int tmp = arr[j];
                arr[j] = arr[j-1];
                arr[j-1] = tmp;
            }
        }
    }
}

02 - 鸡尾酒排序

void cockTailSort(int *arr, int len)
{
    if(NULL == arr || len < 2)
    {
        return;
    }

    int left = 0;
    int right = len - 1;
    int i = 0;

    while(left < right)
    {
        for(i = left; i < right; i++)
        {
            if(arr[i] > arr[i+1])
            {
                int tmp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = tmp;
            }
        }
        right--;

        for(i = right; i > left; i--)
        {
            if(arr[i] < arr[i-1])
            {
                int tmp = arr[i];
                arr[i] = arr[i-1];
                arr[i-1] = tmp;
            }
        }
        left++;
    }
}

03 - 选择排序

/* 选择排序:
 * 从需要排序的队列数据中选择最小的值同第一个值交换,
 * 再从剩下的部分中选择最下的与第二个交换,
 * 最后实现全队列的排序
 */
void selectSort(int *arr, int len)
{
    if(NULL == arr || len < 2)
    {
        return;
    }
    
    int idx, value, i, j;
    for(i = 0; i < len; i++)
    {
        idx = i;
        value =arr[i];
        for(j = i+1; j < len; j++)
        {
            if(arr[j] < value)
            {
                value = arr[j];
                idx = j;
            }
        }
        arr[idx] = arr[i];
        arr[i] = value;
    }
}

04 - 插入排序

/* 直接插入排序:
 * 把n个待排序的元素看成一个有序表和一个无序表。
 * 开始时,有序表中只包含一个元素,无序表中包含n-1个元素。
 * 排序过程中每次从无序表中取出一个元素,
 * 将它插到有序表中的适当位置,使之成为新的有序表。
 * 重复n-1次即可完
 */
void insertSort(int *arr, int len)
{
    if(NULL == arr || len < 2)
    {
        return;
    }

    int i, j, lastSortedElement;
    for(i = 1; i < len; i++)
    {
        lastSortedElement = arr[i];
        for(j = i - 1; j >= 0 && arr[j] > lastSortedElement; j--)
        {
            arr[j+1] = arr[j];
        }

        arr[j+1] = lastSortedElement;
    }
}

05 - 折半排序算法

/* 折半插入排序:
 * 是直接插入排序的升级版本,使用折半查找算法减少关键字的比较次数
 */
void binary_insertionSort(int *arr, int len)
{
    if(NULL == arr || len < 2)
    {
        return;
    }

    int i, j, left, mid, right, lastSortedElement;
    for(i = 1; i < len; i++)
    {
        lastSortedElement = arr[i];
        left = 0;
        right = i - 1;

        while(left <= right)
        {
            mid = (left + right) / 2;
            if(arr[mid] > lastSortedElement)
            {
                right = mid -1;
            }
            else
            {
                left = mid + 1;
            }
        }

        for(j = i -1; j >= left; j--)
        {
            arr[j+1] = arr[j];
        }

        arr[left] = lastSortedElement;
    }
}

06 - 希尔排序

/* 希尔排序(缩小增量排序)
 * 首先将较大的数据集合分割成若干个小组,
 * 然后对每一个小组分别进行插入排序。
 * 此时,插入排序所作用的数据量比较小,插入的效率比较高。
 * */
void shellSort(int *arr, int len)
{
    if(NULL == arr || len < 2)
    {
        return;
    }

    int i, j, maxValue, increment;
    for(increment = len/2; increment >0; increment/=2)
    {
        for(i = increment; i < len; i++)
        {
            maxValue = arr[i];
            for(j = i - increment; j >= 0 && maxValue < arr[j]; j -= increment)
            {
                arr[j + increment] = arr[j];
            }
            arr[j + increment] = maxValue;
        }
    }
}

07 - 堆排序

/* 堆排序:
 * 将待排序序列构造成一个大顶堆(父节点比子节点大, 即arr[i] >= arr[2*i+1] && arr[i] >= arr[2*i + 2]),
 * 此时,整个序列的最大值就是堆顶的根节点。
 * 将其与末尾元素进行交换,此时末尾就为最大值。
 * 然后将剩余n-1个元素重新构成一个堆,这样会得到n个元素的次小值。
 * 如此反复执行,便能得到一个有序序列。
 */

void heapAdjust(int *arr, int i, int len)
{
    if(NULL == arr || i < 0 || len < 0)
    {
        return;
    }

    int child;
    for(; 2 * i + 1 < len; i = child)
    {
        // i是父节点的下表, 2*i+1是左子节点,2*i+2是右子节点
        child = 2 * i +1;

        // 选中两个子节点中较大的值
        if(child < len-1 && arr[child + 1] > arr[child])
        {
            ++child;
        }

        // 比较父节点和子节点中的较大值
        if(arr[i] < arr[child])
        {
            int tmp = arr[i];
            arr[i] = arr[child];
            arr[child] = tmp;
        }
    }
}



void heapSort(int *arr, int len)
{
    if(NULL == arr || len < 0)
    {
        return;
    }

    // 构建大顶堆
    int i;
    for(i = len/2-1; i >= 0; --i)
    {
        heapAdjust(arr, i, len);
    }

    // 调整堆结构,交换堆顶元素和末尾元素
    for(i = len - 1; i > 0; --i)
    {
        // 将堆顶元素与末尾元素进行交换
        int tmp = arr[0];
        arr[0] = arr[i];
        arr[i] = tmp;

        // 重新对堆进行调整
        heapAdjust(arr, 0, i);
    }
}

08 - 归并排序

/* 归并排序:
 * 将数据进行两两分组,每组之间进行排序。
 * 每个小组排序完后,再将这些有序的小组与有序的小组间进行合并排序, 直到最后合并完。
 */
void merge(int *arr, int head, int mid, int tail)
{
    int i,
        left  = mid - head + 1,
        right = tail - mid,
        arrLeft[left + 1],
        arrRight[right+1];

    for(i = 0; i < left; i++)
    {
        arrLeft[i] = arr[head + i];
    }

    for(i = 0; i < right; i++)
    {
        arrRight[i] = arr[mid + i + 1];
    }

    arrLeft[left] = INT_MAX;
    arrRight[right] = INT_MAX;
    left = 0;
    right = 0;

    for(i = 0; i < tail - head + 1; i++)
    {
        if(arrLeft[left] < arrRight[right])
        {
            arr[head + i] = arrLeft[left];
            left++;
        }
        else
        {
            arr[head + i] = arrRight[right];
            right++;
        }
    }
}
void mergeSortRecursion(int *arr, int left, int right)
{
    int mid = (left + right)/2;
    if(left < right)
    {
        mergeSortRecursion(arr, left, mid);
        mergeSortRecursion(arr, mid+1, right);
        merge(arr, left, mid, right);
    }
}


void mergeSortIteration(int *arr, int left, int right)
{
    int low, mid, high, size;
    for(size = 1; size <= right - left; size *= 2)
    {
        low = left;
        while(low + size - 1 <= right - 1)
        {
            mid = low + size - 1;
            high = mid + size;
            if(high > right)
            {
                high = right;
            }
            merge(arr, low, mid, high);
           low = high + 1;
        }
    }
}

09 - 快速排序

/* 快速排序:
 * 先从数列中读取一个数作为基准数
 * 然后将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
 * 再对左右区间重复第二步,直到各区间只有一个数
 */
int partitation(int *arr, int left, int right)
{
    int i,
        tail = left - 1,
        pivot = arr[right];

    for(i = left; i < right; i++)
    {
        if(arr[i] <= pivot)
        {
            tail++;
            int tmp = arr[tail];
            arr[tail] = arr[i];
            arr[i] = tmp;
        }
    }

    int tmp = arr[tail+1];
    arr[tail+1] = arr[right];
    arr[right] = tmp;

    return tail + 1;
}

void quickSort(int *arr, int left, int right)
{
    int pivotIndex;
    if(left < right)
    {
        pivotIndex = partitation(arr, left, right);
        quickSort(arr, left, pivotIndex-1);
        quickSort(arr, pivotIndex + 1, right);
    }
}

以上, 完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值