C语言学习(十三)插入排序,堆排序,归并排序

对老师讲的排序方式深入的理解了一遍,还没来得及全部注释,正在逐步完善,与君共勉!

#include <stdio.h>
#define MAX 10

typedef int ARR[MAX];
typedef int Elementype;
void swap(ARR arr,int i,int j);//交换参数的数值
void insert(ARR arr);//插入排序
void shell(ARR arr);//希尔排序
void print(ARR arr);//打印函数
void heap(ARR arr);//堆排序主体
void heapadjust(ARR arr,int n,int m);//堆排序初始化函数

void mergesort2(ARR arr,int left,int right)//递归的归并排序

void swap(ARR arr,int i,int j)//交换函数
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void insert(ARR arr)//插入排序
{
    int i,j;
    for(i = 1;i < MAX;i++)
    {
        if(arr[i-1] > arr[i])//判断该位与前一位的大小
        {
            Elementype temp = arr[i];//记录待判断的位置
            for(j = i - 1;j >= 0;j--)
            {
                if(arr[j] > temp)
                    arr[j+1] = arr[j];//如果前一个位置大于后一个位置,将前一位覆盖到后一位,循环进行此判断
                else 
                    break;
            }
            arr[j + 1] = temp;//直到不大于待判断位置,将其赋值给此位置的下一位
            print(arr);
        }
    }
}

void shell(ARR arr)//希尔排序,在插入排序的基础上,依次对数组进行再分组,在组内进行插入排序,然后在更少的分组下进行排序,直到组数为一(组数为2^n+或-1,即1,3,5,7,9,15,17.....)
{
    int a[] = {1,3,5};//记录组数
    int k = 2;
    int step = a[k];//在下一次循环使用不同的组数
    int i,j;
    while(k >= 0)
    {
        for(i = step;i < MAX;i++)
        {
            if (arr[i - step] > arr[i])//如分成五组,第0位和第5位为一组,进行排序,第1位和第6位为一组,进行排序......
            {
                Elementype temp = arr[i];
                for(j = i-step;j >= 0;j -= step)//步长为组数,同一组间两个元素相隔step,判断使用插入排序的思想
                {
                    if(arr[j] > temp)
                    {
                        arr[j + step] = arr[j];
                    }
                    else
                        break;
                }
                arr[j+step] = temp;
            }
        }
        step = a[--k];//进行下一个组数的插入排序
        print(arr);
    }
}

void heapadjust(ARR arr,int n,int m)
{
    Elementype temp = arr[n];//记录父母的值
    int i;
    for(i = 2*n+1;i <= m;i = 2*i+1)
    {
        if(i < m && arr[i] < arr[i + 1])//左右子树比较大小
            i++;
        if(arr[i] < temp)//较大的和父母进行比较
            break;
        arr[n] = arr[i];//如果孩子大,孩子覆盖父母
        n = i;
    }
    arr[n] = temp;//将较小的父母的值放在孩子的位置
}

void heap(ARR arr)
{
    int i;
    for(i = (MAX-2)/2;i >= 0;i--)//初始化
    {
        heapadjust(arr,i,MAX-1);//堆处理,最终形成大顶堆
    }
    print(arr);
    printf("**************\n");
    for(i = MAX-1;i > 0;i--)
    {
        swap(arr,0,i);//将最大值放到最后
        heapadjust(arr,0,i-1);//缩小树的范围再次形成大顶堆(排除最大值)
        print(arr);
    }
}

void meige(ARR arr,int left,int mid,int right)//归并
{
    int len = right-left+1;
    Elementype temp[len];
    int k = 0;
    int i = left;//前一个小组的第一个
    int j = mid+1;//后一个小组的第一个
    while(i <= mid && j <= right)
    {
        if(arr[i] < arr[j])
        {
            temp[k++] = arr[i++];//第一个数进行比较,小的放入数组,然后拿下一个数进行比较
        }
        else
        {
            temp[k++] = arr[j++];//比如第一个数比下一组第一个小,放入数组后,i++即后一个与下一组比较,由于组内排序完成,所以只需排组与组之间的数
        }
    }
    while(i <= mid)
    {
        temp[k++] = arr[i++];//把剩下的数放入数组
    }
    while(j <= right)
    {
        temp[k++] = arr[j++];//把剩下的数放入数组
    }
    for(i = 0;i < len;i++)
        arr[left+i] = temp[i];//把临时的数组放入原数组        
}

void mergesort1(ARR arr)//非递归的归并排序
{
    int left,right,mid;
    int i;
    for(i = 1;i < MAX;i *= 2)    
    {
        left = 0;
        while(left + i < MAX)//约束条件为数组中至少还能组成一组进行排序
        {
            mid = left+i-1;//i为每组的长度,mid的为第一租的尾标
            right = (mid+i)<(MAX-1)?(mid+i):(MAX-1);//right为第二组的尾标
            merge(arr,left,mid,right);//调用归并函数,把连续两组间的大小排出,第一次是相邻元素的排序,第二次是两个一组,组与组的排序
            left = right+1;
        }
        print(arr);
    }
}

void mergesort2(ARR arr,int left,int right)//递归的归并排序,思想在组内进行归并排序,然后在组与组间进行归并排序
{
    if(left == right)
    {
        return;
    }
    int mid = (left+right)/2;
    mergesort2(arr,left,mid);//左半组进行组内排序,逐步调用到元素之间的排序并将返回值依次调用
    mergesort2(arr,mid+1,right);
    merge(arr,left,mid,right);//调用归并排序函数
    print(arr);
}
 

猜你喜欢

转载自blog.csdn.net/ls_dashang/article/details/81516014