C语言排序

一、冒泡排序

基本思想:(将相邻两个数比较,小的调到前头)  
1)有n个数(存放在数组a(n)中),第一趟将每相邻两个数比较,小的调到前头,经n-1次两两相邻比较后,最大的数已“沉底”,放在最后一个位置,小数上升“浮起”;  
2)第二趟对余下的n-1个数(最大的数已“沉底”)按上法比较,经n-2次两两相邻比较后得次大的数;  
3)依次类推,n个数共进行n-1趟比较,在第j趟中要进行n-j次两两比较

#include <stdio.h>
#include <windows.h>
int main() 
{
    int a[10] = { 123, 34, 76, 31, 678, 94, 456, 29, 4, 23 };
    for (int j = 0; j < 10; j++)
    {
        for (int i = 0; i < 9; i++)
        {
            if (a[i] > a[i + 1])
            {
                int b = 0;
                b = a[i + 1];
                a[i + 1] = a[i];
                a[i] = b;
                for (int k = 0; k < 10; k++){ printf("%d\t", a[k]); }printf("\n");
                Sleep(500);
            }
        }
    }
}

 

 

 

 

二、选择排序

基本思想:  
1)对有n个数的序列(存放在数组a(n)中),从中选出最小的数,与第1个数交换位置;  
2)除第1 个数外,其余n-1个数中选最小的数,与第2个数交换位置;  
3)依次类推,选择了n-1次后,这个数列已按升序排列。 

 

#include <stdio.h> 
#include <windows.h>
int main()
{
    int a[10] = { 123, 34, 76, 31, 678, 94, 456, 29, 4, 23 };
    for (int i = 0; i < 10; i++)
    {
        int min = i;            //这个十分重要,每次循环之前初始化min的值 并且不再重复用前面的下标
        for (int j = i; j < 10; j++) //这个循环找出最小的那个值的下标
        {
            if (a[j] < a[min])
            {
                min = j;
            }
        }
        if (a[min] != a[i])    //把刚才找到的那个min下标和前面他排名的位置互换
        {
            int b = a[min];
            a[min] = a[i];
            a[i] = b;
        }
        for (int k = 0; k < 10; k++){ printf("%d\t", a[k]); }printf("\n");
    }
}

 

 

 

 

三、直接插入排序

基本思想:  

1)第一个元素自己作为一个有序数组;

2)从第二个元素开始,将它与其左侧第一个元素比较,若左侧第一个元素比它大,则继续与左侧第二个元素比较,直到遇到不大于(小于或等于)该元素的元素,将该元素插入到所找到的元素的右边,此时该元素及其左边的元素是已排序的;

3)选取第 3、4、...、n 个元素,重复步骤 2;

4)得到有序的数

#include <stdio.h> 
#include <windows.h>
int main()
{
    int a[10] = { 123, 34, 76, 31, 678, 94, 456, 29, 4, 23 };
    for (int i = 1; i < 10; i++)//从第二个数开始
    {
        int b = a[i];
        int p = i - 1;
        while (p >= 0 && b < a[p])//把所有比a[i]大的数全换到后面去
        {
            a[p + 1] = a[p];
            p--;
        }
        a[p + 1] = b;
        for (int k = 0; k < 10; k++){ printf("%d\t", a[k]); }printf("\n");
    }
}

 

 

 

 

四、希尔排序

首先、先把一个数组按照一定间隔,分成两两一组的结合,同时对比这两个数据,排序

然后、再按照另一个间隔重复刚才的步骤

接下来、直到间隔为1,也就是相邻的两个数据为一组,做一次直插排序

间隔一般为数组长度的1/2,第二次为1/4,第三次1/8以此类推,直到间隔为1

下列代码中,排序的部分和上面直插排序完全一致。

#include <stdio.h> 
#include <windows.h>
int main()
{
    int a[10] = { 123, 34, 76, 31, 678, 94, 456, 29, 4, 23 };
    int d;                    //每次排序的间隔值
    int x = 0;                //中间变量
    int n = 10;                //数组长度
    d = n / 2;                //初始间隔为数组长度的一半
    while (d >= 1)            //当间隔为1的时候,使用一次插入排序
    {
        for (int i = d; i < n; i++)
        {
            x = a[i];
            int j = i - d;
            while (j >= 0 && a[j]>x)        //使用a[j]和a[i]作为一对去排序
            {
                a[i] = a[j];
                j = j - d;
            }
            a[j + d] = x;
        }
        d = d / 2;
        for (int k = 0; k < 10; k++){ printf("%d\t", a[k]); }printf("\n");
    }
}

 

  

 四、快速排序

第一步,选择一个数作为基准(本例中选择数组最前端那个)

第二步,将后面的所有数字里面,比基数小的放左边,比基数大的放右边

第三步,不断重复第二步。。。

本例中使用左右指针。

#include <stdio.h>
void change(int *a, int *b);
void Sequence(int a[], int q, int p);

int main()
{
    int a[10] = { 12, 13, 15, 20, 0, -1, -10, 100 ,13 ,1};
    Sequence(a, 0, 9);
    for (int k = 0; k < 10; k++){ printf("%d\t", a[k]); }printf("\n");
}

/*互换位置
*/
void change(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

/*快速排序函数
参数说明:
a[]        待排数组
q        左指针的位置
p        右指针的位置
*/
void Sequence(int a[], int q, int p)
{
    int q_1 = q;//q一开始的位置
    int p_1 = p;//p一开始的位置
    int basis = a[q];//基准数据 取数组的第一个数
    //当左右指针相遇时不循环了,此时q=基数所应该在的位置
    if (q >= p){ return; }

    while (q < p)
    {
        //先走p
        //a[p]和基数比较,如果比基数大,指针向前挪动,如果比基数小,则和a[q]换位
        while (q < p && a[p] > basis)
        {
            p--;
        }
        change(&a[q], &a[p]);
        q++;

        //a[q]和基数比较,只要a[q]比基数小,就往右走,直到走到比基数大的数,就和a[p]换位
        while (q < p && a[q] < basis)
        {
            q++;
        }
        change(&a[q], &a[p]);
        p--;
    }
    a[q] = basis;//将最开始选定的基数,赋值给q指针最后指向的地方,也就是basis本应在的位置

    /*
    到这里,第一次循环已经结束了,但是还需要对左右两个大小数组各进行快排
    所以,这两个数组,{0→q-1},{q+1→p}还需要再用同样的方法进行排序
    */

    //此时,q已经是基准数basis所在的位置了,利用一开始存的变量区域放进函数
    Sequence(a, q_1, q - 1);
    Sequence(a, q + 1, p_1);

}

 

123, 34, 76, 31, 678, 94, 456, 29, 4, 23
posted @ 2019-10-23 09:26  祁峰_1024  阅读(338)  评论(0编辑  收藏  举报