白话经典算法系列

原文链接:

http://blog.csdn.net/MoreWindows/article/category/859207

1.冒泡排序

核心思路

双重循环

外层是进行多少轮,一轮冒泡只能排好一个数,所以有n轮;(这是最好的理解方式)

内层是单次冒泡,冒泡的核心是逐个,相邻元素两两比较,如此,一轮冒泡后,最大(最小)元素就跑到最后面了

//核心代码
void sort(int *a, int len)
{
    for (int i = 0; i < len; i++)
        for (int j = 1; j < len - i; j++)
        {
            if (a[j - 1] > a[j])
                swap(a[j - 1], a[j]);
        }
}

实现:外层从0到len-1;内层从1到len-i,因为已经排过的就不需要再参与下一次的冒泡了;两两比较,反序则交换。

改进版1:

核心思想如果某一趟内层没有进行交换,那显然整个数组已经有序,那就可以退出了。

//核心代码
void sort(int *a, int len)
{
    bool flag = true;
    for (int i = 0; i < len; i++)
    {
        for (int j = 1; j < len - i; j++)
        {
            if (a[j - 1] > a[j])
            {
                swap(a[j - 1], a[j]);
                flag = false;
            }
        }
        if (!flag) break;
    }
}

实现:在所有循环外部设置一个标签true,表示此时数组有序;最内层如果交换执行,标签就会被设置为false,表明此时数组无序,仍需进入下一轮;如果内层循环一个也没执行,那标签就是原始的true;在外层循环内设置一个条件跳出器,一旦检测到true就结束外层循环。

改进版,网上有很多有意思的写法,总体就是一个多米诺玩具,相互触发,很好玩

//巧妙的改写版本
void sort(int *a, int len)
{
    int k = len;
    bool flag = true;
    while (flag)
    {
        flag = false;
        for (int j = 1; j < k; j++)
        {
            if (a[j - 1] > a[j])
            {
                swap(a[j - 1], a[j]);
                flag = true;
            }
        }
        k--;
    }
}

 

改进2:

还有一种情况需要改进,即数组前面部分无序,后面有序(3,2,1,4,5,6,7,8)。此时可以记录那个临界的位置,下次内层冒泡的终点就可以提前。

//这种算法还是少些得好,太晦涩
void sort(int *a, int len)
{
    int flag = len;
    while (flag > 0)
    {
        int k = flag;
        flag = 0;
        for (int j = 1; j < k; j++)
        {
            if (a[j - 1] > a[j])
            {
                swap(a[j - 1], a[j]);
                flag = j;
            }
        }
    }
}

2.快速排序

原文地址:https://www.cnblogs.com/leezx/p/5723080.html