排序(四)交换排序

1.冒泡排序(时间复杂度为 O(N2))

原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,

这样一趟过去后,最大或最小的数字被交换到了最后一位;重复此动作直到排好序为止;

先来cv一个动图看看效果:

void BubbleSort(vector<int>& Vector)
{
    for (int i = 0; i < Vector.size(); ++i)
    {
        for (int j = 0; j < Vector.size() - i - 1; ++j)
        {
            if (Vector[j] > Vector[j + 1])
                swap(Vector[j], Vector[j + 1]);
        }
    }
}

/*优化*/ void OptimizeBubbleSort(vector<int>& Vector) { int index = Vector.size() - 1; bool sign = true; while (index && sign) { int tmp = -1; for (int i = 0; i < index; ++i) { if (Vector[i] > Vector[i + 1]) { swap(Vector[i], Vector[i + 1]); tmp = i; } } tmp > 0 ? index = tmp : sign = false; } }

这里奉上一篇关于冒泡排序的博文(超赞): http://blog.csdn.net/lemon_tree12138/article/details/50591859

2.快速排序

快速排序也是一种采用分治法解决问题的一个典型应用。在很多编程语言中,对数组,列表进行的非稳定排序在内部实现中都使用的是快速排序。

借鉴前辈们的动图看下效果先:

快速排序的基本思想如下:

  1. 对数组进行随机化。
  2. 每次从数列中取出最后一个数作为参照;
  3. 将比这个数大或者等于的数放到它的右边,小于它的数放到它的左边。
  4. 再对左右区间重复第三步,直到各区间只有一个数。

举个栗子:

/*方式一:见上图 ↑↑↑↑↑↑*/
int
_QuickSort(vector<int>& Vector, int left, int right) { int middle = left + (right - left) / 2; /*优化一:三数取中*/ int MaxNumber = Max(Vector[left],Max(Vector[middle], Vector[right])); int MinNumber = Min(Vector[left],Min(Vector[middle], Vector[right])); if (Vector[left] > MinNumber && Vector[left] < MaxNumber) swap(Vector[left], Vector[right]); else if (Vector[middle] > MinNumber && Vector[middle] < MaxNumber) swap(Vector[middle],Vector[right]); int begin = left, end = right - 1; int key = Vector[right]; while (begin < end) { while (begin < end && Vector[begin] < key) ++begin; while (begin < end && Vector[end] >= key) --end; swap(Vector[begin], Vector[end]); } if (Vector[begin] > key) { swap(Vector[begin], Vector[right]); return begin; } else { return right; } } /*方式二;挖坑法*/ int _QuickSort(vector<int>& Vector, int left, int right) { int begin = left, end = right; int key = Vector[right]; while (begin < end) { while (begin < end && Vector[begin] < key) ++begin; Vector[end] = Vector[begin]; while (begin < end &&Vector[end] >= key) --end; Vector[begin] = Vector[end]; } Vector[begin] = key; return begin; } /*方式三:前后指针法*/ int _QuickSort(vector<int>& Vector, int left, int right) { int begin = left, small = left - 1, end = right; int key = Vector[right]; while (begin < end) { if (Vector[begin] < key) { ++small; swap(Vector[small], Vector[begin]); } ++begin; } swap(Vector[++small ], Vector[end]); return small; }
void QuickSort(vector<int>& Vector, int left, int right)
    {
        if (right - left > 13)    //优化二:当区间小到一定程度时,使用插入排序
        {
            int middle = _QuickSort(Vector, left, right);
            QuickSort(Vector, left, middle - 1);
            QuickSort(Vector, middle+1, right);
        }
        else
        {
            //插入排序
            InsertSort(Vector, left, right);
        }
    }


/*插入排序*/
void InsertSort(vector<int>& Vector, int left, int right)
    {
        for (int i = left; i<right; ++i)
        {
            int end = i;
            int key = Vector[end + 1];
            while (end >= left && Vector[end] > key)
            {
                Vector[end + 1] = Vector[end];
                --end;
            }
            Vector[end + 1] = key;
        }
    }

算法分析:

  1. 在最好的情况下,快速排序只需要大约nlgn次比较操作,在最坏的情况下需要大约1/2 n次比较操作。
  2. 在最好的情况下,每次的划分都会恰好从中间将序列划分开来,那么只需要lgn次划分即可划分完成,每一次划分都需要比较N次。
  3. 在最坏的情况下,即序列已经排好序的情况下,每次划分都恰好把数组划分成了0,n两部分,那么需要n次划分,但是比较的次数则变成了n, n-1, n-2,….1, 所以整个比较次数约 为 nnndf n(n-1)/2~n2/2.
  4. 平均情况下,快速排序需要大约1.39NlgN次比较,这比合并排序多了39%的比较,但是由于涉及了较少的数据交换和移动操作,他要比合并排序更快。
  5. 快速排序是非稳定性排序。
原文地址:https://www.cnblogs.com/shihaochangeworld/p/5572813.html