码迷,mamicode.com
首页 > 编程语言 > 详细

逆序对个数 - 冒泡排序

时间:2019-03-10 00:01:31      阅读:546      评论:0      收藏:0      [点我收藏+]

标签:function   namespace   数组   返回   函数对象   compare   排序   class   cti   

       设一个序列为: a[0], a[1], ..., a[n-1],一个逆序对是指:{ (a[i], a[j]) | a[i] > a[j], i < j }。

        统计一个序列中的逆序对个数,可以使用冒泡排序法、二路归并法等。这里介绍利用冒泡排序统计逆序对个数的方法。

        核心思想:冒泡排序中,每进行一次交换,则序列的逆序对个数-1。

        证明:设冒泡排序过程中 a[i] 与 a[i+1] 进行了一次交换,这说明 a[i] > a[i+1]。序列中逆序对可分为四种:① 非 a[i] 和非 a[i+1] 构成的逆序对;②  a[i] 和非 a[i+1] 构成的逆序对;③  a[i+1] 和非 a[i] 构成的逆序对;④  a[i] 和 a[i+1] 构成的逆序对。易知,a[i] 与 a[i+1]  交换时,①、②、③ 类型构成的逆序对个数没变,而类型④的逆序对个数由1变为0,故每进行一次交换序列逆序对个数减少1。

       冒泡排序统计逆序对的C++程序:

#include <cstdio>
#include <string>
#include <functional>
using namespace std;

/* 对T类型的数组a[lo, hi)进行排序,并返回逆序对个数。
   比较由函数对象compare实现,compare(a, b):当 a <= b,返回true。*/
template <class T, class Comp>
int countInversionBubble(T * a, int lo, int hi, Comp compare)
{
    int n_inv = 0;    // 逆序对个数
    while ( lo < hi - 1 )
    {
        int last = lo - 1;    // last标示一轮气泡中最后一次交换发生在a[i]与a[i+1]间。
        for ( int i = lo; i < hi - 1; ++i )
        {
            if ( !compare(a[i], a[i+1]) )
            {
                T t = a[i+1]; a[i+1] = a[i]; a[i] = t;    // 交换a[i]与a[i+1] 
                ++n_inv; 
                last = i;
            }
        }
        hi = last + 1;
    }
    return n_inv; 
}

// 测试
int main() { int a1[] = {1}; int n1 = countInversionBubble(a1, 0, 1, less<int>()); // 0 int a2[] = {1, 2, 3}; int n2 = countInversionBubble(a2, 0, 3, less<int>()); // 0 int a3[] = {5, 4, 3, 2, 1}; int n3 = countInversionBubble(a3, 0, 5, less<int>()); // 10 int a4[] = {5, 1, 3, 2, 4}; int n4 = countInversionBubble(a4, 0, 5, less<int>()); // 5 printf("%d %d %d %d\n", n1, n2, n3, n4); return 0; }

      

逆序对个数 - 冒泡排序

标签:function   namespace   数组   返回   函数对象   compare   排序   class   cti   

原文地址:https://www.cnblogs.com/fyqq0403/p/10503237.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!