C语言数据结构——如何排序

刚接触排序时感觉排序非常的复杂,排序所用到的循环嵌套、函数递归调用都不容易理解,所以我把以前写过的排序程序做的总结,写在一个程序中,便于比较和以后温习。

算法描述:下面是我对每一种算法的理解(从小到大排序)
(1)冒泡排序:
n个数进行排序,从第一个数开始两两比较,较大的数在后面,n-1比较后最大的数就到了最后一位,排除最后一位,重复这个过程。
(2)选择排序:
n个数进行排序,选择第一个数与后面的数依次比较,较小的数放在第一个位置上,比较n-1次后,第一个位置上是最小的数,排除第一个数,重复该过程。
(3)插入排序:
从第一个元素开始,这个元素可以认为已经被排序,取出下一个元素,在已经排序的元素序列中从后向前扫描,如果该元素(已排序)大于新元素,将该元素移到下一位置,直到找到一个位置使序列有序,重复上述步骤。
(4)希尔排序:
希尔排序是插入排序的进化版,适合大量数据的排序。首先取一个整数增量d1,将要排序的数分为d1个组,所以距离为d1的数放在同一组中,组内进行插入排序。再取第二个增量d2小于d1,重复上述分组排序步骤,知道增量为1,再进行插入排序。
(5)堆排序:
堆排序是对选择排序的改进,使用树结构记录选择排序的过程,其中的关键是构造大顶堆。首先将所有元素构造成一个大顶堆,将第一个元素与最后一个元素调换,排除最后一个元素,再次构造大顶堆,重复该过程。
(6)归并排序:
递归实现:把长度为n的输入序列分成两个长度为n/2的子序列,对这两个子序列分别采用归并排序,将两个排序好的子序列合并成一个最终的排序序列。
非递归实现:首先进行是两两归并,然后四四归并,然后是八八归并,一直下去直到归并了整个数组。
(7)快速排序:
从数列中挑出一个元素,称为 “基准”(pivot),重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面,递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。

代码实现:

#include <stdio.h>
#include <time.h>
#define MAX 10

typedef char ElementType;
typedef ElementType ARR[MAX];  //ARR = ElementType  [MAX]

int len = sizeof(ARR) / sizeof(ElementType);

void swap(ARR arr,int i,int j);
void print(ARR arr);
void bubble1(ARR arr);//冒泡排序
void bubble2(ARR arr);//冒泡排序改进
void select (ARR arr);//选择排序
void insert (ARR arr);//插入排序
void shell  (ARR arr);//希尔排序

void heap   (ARR arr);//堆排序
void heapadjust(ARR arr,int i,int m);

void Merging1(ARR arr,int left,int right);//归并排序
void Merging2(ARR arr,int left,int right);
void Merge(ARR arr,int left,int mid,int right);

void Quick  (ARR arr,int low,int high); //快速排序
int pivotkey1(ARR arr,int low,int high);
int pivotkey2(ARR arr,int low,int high);
ElementType getpivot(ARR arr,int low,int high);
void Qsort(ARR arr,int low,int high);

int main()
{
    ARR arr1={10,9,8,7,6,5,4,3,2,1};
    ARR arr2={10,1,2,3,4,5,6,7,8,9};
    ARR arr3={0,9,8,5,3,1,4,7,2,6};
   // printf("bubble1 :\n");
   // bubble1(arr1);
   // 
   // printf("bubble1 :\n");
   // bubble2(arr1);
   // 
   // printf("select :\n");
   // select(arr1);
   // 
   // printf("insert :\n"); 
   // insert(arr3);
   // 
   // printf("shell :\n");
   // shell(arr3);
   // 
   // printf("heap :\n"); 
   // heap(arr3);

   // printf("Merging1 :\n");
   // Merging1(arr1,0,9);

   // printf("Merging2 :\n");
   // Merging2(arr1,0,9);

    printf("Quick :\n");
    Quick(arr1,0,9);
    return 0;
}

void swap(ARR arr,int i,int j)
{
    ElementType temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void print(ARR arr)
{
    int i;
    for(i = 0;i < len;i++)
    {
        printf("%3d",arr[i]);
    }
    printf("\n");
}

void bubble1(ARR arr)
{
    int i,j;
    for(i = 0;i < len-1;i++)
    {
        print(arr);
        for(j = 0;j < len-1-i;j++)
        {
            if(arr[j] > arr[j+1])
            {
                swap(arr,j,j+1);
            }
        }
    }
}

void bubble2(ARR arr)
{
    int i,j;
    int flag;
    for(i = 0;i < len-1;i++)
    {
        flag = 0;
        print(arr);
        for(j = 0;j < len-1-i;j++)
        {
            if(arr[j] > arr[j+1])
            {
                flag = 1;
                swap(arr,j,j+1);
            }
        }
        if(flag == 0)
        {
            break;
        }
    }   
}

void select (ARR arr)
{
    int i,j;
    int min;
    for(i = 0;i < len-1;i++)
    {
        min = i;
        print(arr);
        for(j = i+1;j < len;j++)
        {
            if(arr[j] < arr[min])
            {
                min = j;
            }
        }
        if(min != i)
        {
            swap(arr,i,min);
        }
    }
}

void insert (ARR arr)
{
    int i,j;
    ElementType temp;
    for(i = 1;i < len;i++)
    {
        temp = arr[i];
        if(arr[i-1] > 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)
{
    int i,j;
    int increment = len;//定义一个增量;
    ElementType temp;
    while(increment > 1)
    {
        increment = increment / 3 + 1;//如此改变增量,最后一个增量一定是1;
        printf("%d:\n",increment);
        for(i = increment;i < len;i++)
        {
            if(arr[i] < arr[i - increment])
            {
                temp = arr[i];
                for(j = i - increment;j >= 0 && arr[j] > temp;j -= increment)
                {
                    arr[j + increment] = arr[j];  //这个for循环是用来交换位置的,终止循环时j会
                                                  //停在要插入的数处,插入时插向下一个位置;
                }
                arr[j+increment] = temp;
            }
        }
        print(arr);
    }

}
//堆排序
void heap (ARR arr)
{
    int i;
    ElementType temp;
    for(i = len/2;i > 0;i--)
    {
        heapadjust(arr,i,len);//开始时数组并无顺序,排len/2个结点;
    }
    for(i = len;i > 1;i--)
    {
        temp = arr[i];
        arr[i] = arr[1];      //交换第一个和排序的最后一个;
        arr[1] = temp;
        heapadjust(arr,1,i-1);//最后一个脱离排序;
    }
    print(arr);
}

void heapadjust(ARR arr,int i,int m)
{
    int j;
    ElementType temp;
    temp = arr[i];
    for(j = i * 2;j <= m;j *= 2)
    {
        if(j < m && arr[j] < arr[j+1])
        {
            ++j;
        }
        if(temp >= arr[j])
            break;
        arr[i] = arr[j];
        i = j;
    }
    arr[i] = temp;      
}

//递归的归并排序
void Merging1(ARR arr,int left,int right)
{
    int mid;
    if(left == right)
    {
        return;
    }
    mid = (left + right) / 2;
    Merging1(arr,left,mid);
    Merging1(arr,mid+1,right);
    Merge(arr,left,mid,right);
}

//非递归的归并排序
void Merging2(ARR arr,int left,int right)
{
    int i;
    int k = 1;
    int len = (right - left + 1);
    int mid;
    while(k <= len)
    {
        i = left;
        while(i < right -2*k + 1)//why????
        {
            mid = i + k - 1 ;
            Merge(arr,i,mid,i+2*k-1);
            i = i + 2*k;
        }
        if(i < right - k + 1)
            Merge(arr,i,i+k-1,right);
        k = 2 * k;
        print(arr);
    }
    return;
}

void Merge(ARR arr,int left,int mid,int right)
{
    int i = left;
    int j = mid + 1;
    int len = right - left + 1;
    ElementType temp[len];
    int k = 0;
    while(i <= mid && j <= right)
    {
        if(arr[i] > arr[j])
            temp[k++] = arr[j++];
        else
            temp[k++] = arr[i++];
    }
    while(i <= mid)
    {
        temp[k++] = arr[i++];
    }
    while(j <= right)
    {
        temp[k++] = arr[j++];
    }
    for(i = 0;i < len;i++)
    {
        arr[i+left] = temp[i];
    }
}

//快速排序
void Quick  (ARR arr,int low,int high)
{
    int pivot;
    if(low < high)
    {
        pivot = pivotkey1(arr,low,high);//pivot = pivotkey2(arr,low,high);
        Quick(arr,low,pivot-1);
        Quick(arr,pivot+1,high); //pivot处不再参与排序
    }
    print(arr);
}

int pivotkey1(ARR arr,int low,int high)
{
    ElementType pivot;
    pivot = getpivot(arr,low,high);
    while(low < high)
    {
        while(low < high && arr[high] > pivot)
        {
            high--;
        }
        swap(arr,low,high);
        while(low < high && arr[low] < pivot)
        {
            low++;
        }
        swap(arr,low,high);
    }
    return low;
}

int pivotkey2(ARR arr,int low,int high)
{
    ElementType pivot;
    pivot = arr[low];   //pivot = getpivot(arr,low,high);
    int i;
    int tail = low + 1;
    for(i = low + 1;i <= high;i++)
    {
        if(arr[i] <= pivot)
            swap(arr,i,tail++);
    }
    swap(arr,low,tail-1);
    return tail-1;
}

ElementType getpivot(ARR arr,int low,int high)
{
    int mid = (low + high) / 2;
    if(arr[low] > arr[high])
        swap(arr,low,high);
    if(arr[mid] > arr[high])
        swap(arr,mid,high);
    if(arr[mid] > arr[low])
        swap(arr,mid,low);
    return arr[low];
}

void Qsort(ARR arr,int low,int high) //改进了Quick函数
{
    int pivot;
    while(low < high)
    {
        pivot = pivotkey1(arr,low,high);//pivot = pivotkey2(arr,low,high);
        Quick(arr,low,pivot-1);
        low = pivot - 1;
    }
    print(arr);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值