首页 > 编程语言 > 详细

C语言——排序

时间:2021-06-04 12:08:16      阅读:13      评论:0      收藏:0      [点我收藏+]

排序

1.插入排序

(1).代码实现
//插入排序  
void InsertSort(int array[], int size)
{
    for (int i=1;i<size;i++)
    {
        int end = i - 1;
        int key = array[i];
        //寻找插入位置
        while (end>=0&&array[end]>key)
        {
            array[end+1] = array[end];
            end--;
        }
        //插入元素
        array[end + 1] = key;
    }
}
(2).特性

? a. 元素集合越接近有序,直接插入排序算法的时间效率越高

? b. 时间复杂度:O(N^2)

? c.空间复杂度:O(1),它是一种稳定的排序算法

? d. 稳定性:稳定

2.希尔排序

(1).代码实现
//希尔排序
void ShellSort(int array[], int size)
{
    int gap = size;
    while (gap > 1)
    {
        gap = gap / 3 + 1;
        for (int i = gap; i < size; i++)
        {
            int end = i - gap;
            int key = array[i];
            while (end>=0&&array[end]>key)
            {
                array[end+gap] = array[end];
                end=end-gap;
            }
            array[end + gap] = key;
        }
    }
}
(2).特性

? a. 希尔排序是对直接插入排序的优化

? b. 希尔排序的时间复杂度不好计算,需要进行推导,推导出来平均时间复杂度: O(N^1.3—N^2)

? c.稳定性:不稳定

3.选择排序

(1).代码实现
void swap(int arr1[], int arr2[])
{
    int temp = 0;
    temp = *arr1;
    *arr1 = *arr2;
    *arr2 = temp;
}
//选择排序
void SelectSort(int array[], int size)
{
    for(int i=0;i<size-1;i++)//最后剩一个数就不用排了,因此是size-1
    {
        int maxPos = 0;
        //寻找最大值的位置
        for (int j = 1; j < size - i; j++)
        {
            if (array[j] > array[maxPos])
            {
                maxPos = j;
            }
        }
        //将最大值放在数组最后
        if (maxPos != size - 1 - i)
        {
            swap(&array[maxPos], &array[size - 1 - i]);
        }
    }
}
//选择排序另一种方法
void SelectSortOP(int array[], int size)
{
    int begin = 0,end = size - 1;
    while (begin < end)
    {
        //找最大最小元素位置
        int maxPos = begin;
        int minPos = begin;
        int index = begin + 1;
        while (index <= end)
        {
            if (array[index] > array[maxPos])
            {
                maxPos = index;
            }
            if (array[index] < array[minPos])
            {
                minPos = index;
            }
            index++;
        }
        if (maxPos != end)
        {
            swap(&array[maxPos], &array[end]);
        }
        //如果最小的元素恰巧在end处,则上面操作会改变最小元素的位置
        if (minPos == end)
        {
            minPos = maxPos;
        }
        if (minPos != begin)
        {
            swap(&array[minPos], &array[begin]);
        }
        begin++;
        end--;
    }
}
(2).特性

? a.直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用

? b.时间复杂度:O(N^2)

? c.空间复杂度:O(1)

? d.稳定性:不稳定

4.堆排序

(1).代码实现
void swap(int arr1[], int arr2[])
{
    int temp = 0;
    temp = *arr1;
    *arr1 = *arr2;
    *arr2 = temp;
}
//向下调整算法
void HeapAdjust(int array[], int size, int parent)
{
    //先标记左孩子,parent可能有左没有右
    int child = parent * 2 + 1;
    while (child<size)
    {
        //找到左右孩子中较大的,用child标记
        if (child+1 < size && array[child] < array[child + 1])
        {
            child += 1;
        }
        //如果双亲结点小于较大的子结点,则交换
        if (array[parent] < array[child])
        {
            swap(&array[parent], &array[child]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            return;
        }
    }

}
//堆排序
void HeapSort(int array[], int size)
{
    int end = size - 1;
    //建堆, 升序-->大堆    降序-->小堆
    //从倒数第一个非叶子结点到根结点一直向下调整
    for (int root = (end - 1) / 2; root >= 0; root--)
    {
        HeapAdjust(array, size, root);
    }
    //排序
    while(end)
    {
        swap(&array[0], &array[end]);
        HeapAdjust(array, end , 0);
        end--;
    }
}
(2).特性

? a.堆排序使用堆来选数,效率就高了很多

? b.时间复杂度:O(N*logN)

? c.空间复杂度:O(1)

? d.稳定性:不稳定

6.冒泡排序

(1).代码实现
//冒泡排序
void BubbleSort(int array[], int size)
{
    for (int i = 0; i < size - 1; i++)
    {
        int flag=0;
        //相邻两个元素比较,不满足就交换
        for (int j = 0; j < size - i-1; j++)
        {
            if (array[j]>array[j+1])
            {
                flag=1;
                swap(&array[j] ,&array[j+1]);
            }   
        }
        if(!flag)//如果flag为0,则没有发生交换,则数组已经有序,就不用再比较了
        {
            return;
        }
    }
}
(2).特性

? a.时间复杂度:O(N^2)

? b.空间复杂度:O(1)

? c.稳定性:稳定

7.计数排序

(1).代码实现
//计数排序
void CountSort(int array[], int size)
{
    //1.找数据范围
    int max = array[0];
    int min = array[0];
    int index = 0;
    for (int i = 0; i < size; i++)
    {
        if (array[i] > max)
        {
            max = array[i];
        }
        if (array[i] < min)
        {
            min = array[i];
        }
    }
    //2.申请空间
    int* count = (int*)calloc(max - min + 1, sizeof(int));
    if (NULL == count)
    {
        return NULL; 
    }
    //3.统计每个元素出现次数
    for (int i = 0; i < size; i++)
    {
        count[array[i] - min]++;
    }
    //4.array数组排序
    for (int i=0;i<max-min+1;i++)
    {
        while (count[i]--)
        {
            array[index++] = i + min;
        }
    }
    free(count);
}
(2).特性

? a. 计数排序在数据范围集中时,效率很高,但是适用范围及场景有限

? b. 时间复杂度:O(MAX(N,范围))

? c. 空间复杂度:O(范围)

? d. 稳定性:稳定

8.快速排序

(1).代码实现
//第一种:hoare法
int Partion1(int array[], int left, int right)
{
    int begin = left;
    int end = right - 1;
    int key = array[end];//基准值是最后一个元素
    while (begin < end)
    {
        while (begin<end&&array[begin] <= key) //保证有效区间
        {
            begin++;
        }
        while (begin < end&&array[end] >= key)   
        {
            end--;  
        }
        if (begin < end)
        {
            swap(&array[begin], &array[end]);
        }
    }
    if (begin!=right-1)
    {
        swap(&array[begin], &array[right - 1]);//将基准值放在数组中间
    }
    return begin;//返回基准值位置
}
//第二种:挖坑法   
int Partion2(int array[], int left, int right)
{
    int begin = left;
    int end = right - 1;
    int key = array[end];
    while (begin < end)
    {
        //begin从前往后找,找比基准值大的元素 
        while (begin < end&&array[begin] <= key)
        {
            begin++;
        }
        if (begin < end)
        {
            array[end] = array[begin];
            end--;
        }

        while (begin < end&&array[end] >= key)
        {
            end--;
        }
        if (begin < end)
        {
            array[begin] = array[end];
            begin++;
        }
    }
    array[begin] = key;
    return begin;
}
//第三种
int Partion3(int array[], int left, int right)
{
    int cur = left;
    int prev = cur-1;
    int key = array[right - 1];
    while (cur < right) 
    {
        if (array[cur] < key&&++prev != cur)
        {
            swap(&array[cur], &array[prev]);
        }
        cur++;
    }
    if (++prev != right - 1)//将基准值放在正确的位置
    {
        swap(&array[prev], &array[right-1]);
    }
    return prev;
}

void QuickSort(int array[], int left, int right)
{
    int div = 0;
    if (right - left <= 1)
    {
        return;
    }
    //找基准值对区间中的数据进行划分,div表述划分好等候基准值位置
    div = Partion3(array, left, right);
    //递归
    QuickSort(array, left, div);
    QuickSort(array, div+1, right);
}
(2).特性

? a. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序

? b. 时间复杂度:O(N*logN)

? c. 空间复杂度:O(logN)

? d. 稳定性:不稳定

9.归并排序

(1).代码实现
//合并两个有序数组
void MergeData(int array[], int left, int mid, int right, int temp[])
{
    int begin1 = left, end1 = mid;
    int begin2 = mid , end2 = right;
    int index = left;
    while (begin1 < end1 && begin2 < end2)
    {
        if (array[begin1] <= array[begin2])
        {
            temp[index++] = array[begin1++];
        }
        else
        {
            temp[index++] = array[begin2++];
        }
    }
    while (begin1<end1)
    {
        temp[index++] = array[begin1++];
    }
    while (begin2 < end2)
    {
        temp[index++] = array[begin2++];
    }
}
//归并排序
void MergeSort(int array[], int left, int right, int temp[])
{
    if (right - left <= 1)
    {
        return;
    }
    int mid = left + ((right - left) / 2);

    MergeSort(array, left, mid, temp);
    MergeSort(array,mid , right, temp);
    MergeData(array, left, mid, right, temp);   
    memcpy(array + left, temp+left, sizeof(array[0])*(right - left));
}
(2).特性

? a. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。

? b. 时间复杂度:O(N*logN)

? c. 空间复杂度:O(N)

? d. 稳定性:稳定

C语言——排序

原文:https://blog.51cto.com/u_15153653/2855818

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!