排序算法总结

Posted 宇哲_安菲尔德

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法总结相关的知识,希望对你有一定的参考价值。

今天,我们来总结一下排序算法:
排序分为冒泡排序,选择排序,插入排序,希尔排序,合并排序,快速排序,堆排序,基数排序等等,本篇文章我来详细解析冒泡排序,选择排序,直接插入排序。

冒泡排序

首先说说最简单的冒泡排序:从老谭那本书就开始认识冒泡排序了,这种方法简单易懂:
这里写图片描述
这张动图可以解释冒泡排序。
接下来,看代码的实现:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void BubbleSort(char *p)
{
    int i = 0;
    int len = strlen(p);
    int j = 0;
    assert(p);
    for (i = 0; i < len - 1; i++)
    {

        for (j = 0; j < len - 1 - i; j++)
        {
            if (*(p + j) > *(p + j + 1))        //进行比较交换
            {
                char tmp = *(p + j);
                *(p + j) = *(p + j + 1);
                *(p + j + 1) = tmp;

            }
        }

    }
}
int main()
{
    char p[] = "174521789";
    BubbleSort1(p);
    printf("%s\\n", p);
    system("pause");
    return 0;
}

仔细想一想你就会发现冒泡排序的效率非常低,所以我们当然要选择对此进行优化了,
这里写图片描述

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//冒泡排序第一种优化方式:给标志位,不需要进行对有序的进行冒泡排序。
void BubbleSort1(char *p)
{
    int i = 0;
    int len = strlen(p);
    int j = 0;
    int flag = 0;                           //给一个标志
    for (i = 0; i < len - 1; i++)
    {
        flag = 1;                           //把标志置1
        for (j = 0; j < len - 1 - i; j++)
        {
            if (*(p + j) > *(p + j + 1))
            {
                char tmp = *(p + j);
                *(p + j) = *(p + j + 1);
                *(p + j + 1) = tmp;
                flag = 0;                   //冒泡了以后把标志置0
            }
        }
        if (flag)                           //判断标志,如果标志为1表示后面的都为有序,所以不需要再冒泡
        {
            break;
        }
    }
}
int main()
{
    char p[] = "17452198";
    BubbleSort2(p);
    printf("%s\\n", p);
    system("pause");
    return 0;
}

上述我们通过flag使得最后对于一些有序的避免了排序,但是,作为一个应该精益求精的人,我想我们都应该做到更好,在这,提供另外一种优化的方法:

//冒泡排序第二种优化方式:记住最后排序好的位置,然后就不需要冒泡后续的。
void BubbleSort2(char *p)
{
    int i = 0;
    int len = strlen(p);
    int j = 0;
    int k = len-1;
    int tmp = 0;
    int m = 0;                              //记录你进行冒泡后最后移动到的位置
    int flag = 0;                           //给一个标志
    for (i = 0; i < len - 1; i++)
    {
        flag = 1;                           //把标志置1
        m = 0;
        for (j = 0; j < k; j++)             //每次进行排序的只有前一半部分
        {
            if (*(p + j) > *(p + j + 1))
            {
                char tmp = *(p + j);
                *(p + j) = *(p + j + 1);
                *(p + j + 1) = tmp;
                flag = 0;                   //冒泡了以后把标志置0
                m = j;                      //记录每一次的位置
            }
        }
        if (flag)                           //判断标志,如果标志为1表示后面的都为有序,所以不需要再冒泡
        {
            break;
        }
        k = m;                              //记住最后排序到的位置,后面再排序就直排前面的
    }

}

int main()
{
    char p[] = "17452198";
    BubbleSort2(p);
    printf("%s\\n", p);
    system("pause");
    return 0;
}

这里借助临时变量记住最后一次交换的位置,作为内层循环的边界。

插入排序

这里写图片描述
上面这张图片就是揭示了插入排序算法的实现过程。在前面为有序的序列,后面为无序序列,把有序序列后的一个每次和有序序列中的元素相比较,插入到它应该出现的位置。
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法步骤:

1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
void InsertionSort(char *p)
{
    assert(p);
    int len = strlen(p);
    int i = 0;
    int j = 0;
    for (i = 1; i < len - 1; i++)
    {
        char tmp = p[i];                //在这里保存有序序列后的一个元素
        for (j = i - 1; j >= 0; j--)    //进行和有序序列中的元素进行比较
        {
            if (tmp < p[j])             //比较判断
            {
                p[j + 1] = p[j];        //进行有序序列元素的移动
            }
            else
            {
                break;                  
            }
        }
        p[j+1] = tmp;                   //进行元素插入
    }

}


int main()
{
    char str[] = "17452198";
    InsertionSort(str);
    printf("%s\\n", str);
    system("pause");
    return 0;
}

选择排序

这里写图片描述

这个动图就可以说明选择排序的问题了。
选择排序(Selection sort)也是一种简单直观的排序算法。

算法步骤:

1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

2)再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

3)重复第二步,直到所有元素均排序完毕。

#define _CRT_SECURE_NO_WARNINGS 1





#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<assert.h>
void SelectSort(char *str)
{
    assert(str);
    int i = 0;
    int min = 0;
    int j = 0;
    int len = strlen(str);
    for (i = 1; i < len - 1; i++)
    {
        min = i + 1;                        //首先默认无序第一个为最小的
        for (j = i + 1; j < len - 1; j++)
        {
            if (str[min]>str[j])            
            {
                min = j;                    //进行无序序列中的比较,得到最小的下标
            }
        }
        if (min != i)                       //把无序序列中最小的元素与有序的元素进行替换
        {
            char tmp = str[i];
            str[i] = str[min];
            str[min] = tmp;
        }
    }
}

int main()
{
    char str[] = "17452198";
    SelectSort(str);
    printf("%s\\n", str);
    system("pause");
    return 0;
}

这次就先描述这三种排序算法,后续依然会有更新

以上是关于排序算法总结的主要内容,如果未能解决你的问题,请参考以下文章

排序算法总结

排序算法总结——冒泡排序与鸡尾酒排序

排序算法总结:冒泡排序

常用排序算法总结1一一冒泡排序

常用排序算法总结1一一冒泡排序

算法——排序算法个人总结