スポンサーリンク

C++でpartitionするプログラムを変更して[pivot未満][pivot][pivotより大きい]の領域に分割する

#include <iostream>
#include <vector>
#include <array>

// 配列の分割を行う関数
template<typename Container, class PCond>
int64_t partition(Container& arr, int64_t low, int64_t high, PCond& pivot) {

    int64_t i = low;
    int64_t j = high-1;

    int64_t bound;
    while (true) {

        // 条件に合致するものを探す
        while ( (pivot.IsTrue(i) == true) ) {

            i++;
            if (i >= high)
                break;
        }
        // 条件に合致しないものを探す
        while ( (pivot.IsFalse(j) == true) ) {

            j--;
            if (j == -1)
                break;
        }

        // 左右の走査が交差した場合に分割終了
        if (i >= j) {
            bound = i;
            break;
        }

        // 条件に合致しない要素とする要素を交換
        pivot.Swap(i, j);

        // 走査を進める
        i++;
        j--;
    }
    return bound;
}
enum BoolType {
	True = 1,
	False = 0
};
using PairTypeBool = std::pair<BoolType, std::string>;
using PairTypeFloat = std::pair<float, std::string>;

// データを分割する時に必要な関数をまとめたもの
struct PartitionFuncBool {
    std::vector<PairTypeBool>& _array;
    int64_t _pivot;
    float _value;

    PartitionFuncBool(std::vector<PairTypeBool>& arr,int64_t pivot_index):_array(arr) {
        _pivot = pivot_index;
        _value = _array[_pivot].first;
    }

    // 要素の交換関数
    void Swap(size_t i, size_t j) {

        // pivotが移動したので最新のindexを保存
        if(i==_pivot) 
            _pivot = j;
        else if(j==_pivot) 
            _pivot = i;

        std::swap(_array[i], _array[j]);
    }

    // 条件判定関数
    bool IsTrue(size_t i) {
        return _array[i].first == _value;
    }
    bool IsFalse(size_t i) {
        return !IsTrue(i);
    }

};
      
// データを分割する時に必要な関数をまとめたもの
struct PartitionFuncFloat {
    std::vector<PairTypeFloat>& _array;
    int64_t _pivot;
    float _value;

    PartitionFuncFloat(std::vector<PairTypeFloat>& arr, int64_t pivot_index) :_array(arr) {
        _pivot = pivot_index;
        _value = _array[_pivot].first;
    }

    // 要素の交換関数
    void Swap(size_t i, size_t j) {

        // pivotが移動したので最新のindexを保存
        if (i == _pivot)
            _pivot = j;
        else if (j == _pivot)
            _pivot = i;

        std::swap(_array[i], _array[j]);
    }

    // 条件判定関数
    bool IsTrue(size_t i) {
        return _array[i].first <= _value;
    }
    bool IsFalse(size_t i) {
        return !IsTrue(i);
    }
};
      
template<typename Container, class PCond>
std::array<int64_t, 3> partition_3area(Container& arr, int64_t low, int64_t high, PCond& cond) {
    int64_t bound_idx = partition< Container, PCond>(arr, low, high, cond);
    
    // cond._pivot ... 移動後のpivotのindex                 前半にあるはず
    // bound_idx ... 条件に合致しない要素の最初のindex      後半にあるはず

    // pivotが前半の末尾以外にある場合は、前半末尾へ移動
    if(cond._pivot != bound_idx-1)
		cond.Swap(cond._pivot, bound_idx-1);

    return {
        low,
        bound_idx-1,// 移動後のpivot
        high
    };
}
      
void testbool() {

    std::vector<PairTypeBool> arr;

    arr.push_back(std::make_pair(True, "a"));
    arr.push_back(std::make_pair(False, "b"));
    arr.push_back(std::make_pair(False, "c"));
    arr.push_back(std::make_pair(True, "d"));
    arr.push_back(std::make_pair(True, "e"));
    arr.push_back(std::make_pair(True, "f"));
    arr.push_back(std::make_pair(False, "g"));
    arr.push_back(std::make_pair(True, "h"));
    arr.push_back(std::make_pair(False, "i"));
    arr.push_back(std::make_pair(True, "j"));


    std::cout << "分割前の配列: " << std::endl;
    for (size_t i = 0; i < arr.size(); i++) {
        std::cout << "[" << i << "] " << arr[i].first << " " << arr[i].second << std::endl;
    }

    PartitionFuncBool cond(arr, arr.size() / 2);               // ピボットの値を取得
    // ピボット表示
    std::cout << "ピボット: " << "[" << cond._pivot << "]" << arr[cond._pivot].first << " " << arr[cond._pivot].second << std::endl;
    auto ret = partition_3area(arr, (size_t)0, arr.size(), cond);

    std::cout << "分割後の配列: " << std::endl;
    for (size_t i = ret[0]; i < ret[1]; i++) {
        std::cout << "[" << i << "] " << arr[i].first << " " << arr[i].second << std::endl;
    }
    std::cout << std::endl;
    std::cout << "[" << ret[1] << "] " << arr[ret[1]].first << " " << arr[ret[1]].second << std::endl;

    std::cout << std::endl;
    for (size_t i = ret[1] + 1; i < ret[2]; i++) {
        std::cout << "[" << i << "] " << arr[i].first << " " << arr[i].second << std::endl;
    }

}
      
void testfloat() {
    std::vector<PairTypeFloat> arr;

    arr.push_back(std::make_pair(3.7 , "a"));
    arr.push_back(std::make_pair(2.3 , "b"));
    arr.push_back(std::make_pair(7.5 , "c"));
    arr.push_back(std::make_pair(1.2 , "d"));
    arr.push_back(std::make_pair(6.8 , "e"));
    arr.push_back(std::make_pair(5.6 , "f"));
    arr.push_back(std::make_pair(2.4 , "g"));
    arr.push_back(std::make_pair(0.9 , "h"));
    arr.push_back(std::make_pair(6.1 , "i"));
    arr.push_back(std::make_pair(5.3 , "j"));
    arr.push_back(std::make_pair(4.5 , "k"));
    arr.push_back(std::make_pair(8.2 , "l"));
    arr.push_back(std::make_pair(9.1 , "m"));
    arr.push_back(std::make_pair(1.7 , "n"));
    arr.push_back(std::make_pair(5.3 , "o"));
    arr.push_back(std::make_pair(7.7 , "p"));
    arr.push_back(std::make_pair(3.8 , "q"));
    arr.push_back(std::make_pair(4.2 , "r"));

    std::cout << "分割前の配列: " << std::endl;
    for (size_t i = 0; i < arr.size(); i++) {
        std::cout << "[" << i << "] " << arr[i].first << " " << arr[i].second << std::endl;
    }

    PartitionFuncFloat cond(arr, arr.size()/2);               // ピボットの値を取得
    // ピボット表示
    std::cout << "ピボット: " << "[" << cond._pivot << "]" << arr[cond._pivot].first << " " << arr[cond._pivot].second << std::endl;
    auto ret = partition_3area(arr, (size_t)0, arr.size(), cond);

    std::cout << "分割後の配列: " << std::endl;
    for (size_t i = ret[0]; i < ret[1]; i++) {
        std::cout << "[" << i << "] " << arr[i].first << " " << arr[i].second << std::endl;
    }
    std::cout << std::endl;
    std::cout << "[" << ret[1] << "] " << arr[ret[1]].first << " " << arr[ret[1]].second << std::endl;

    std::cout << std::endl;
    for (size_t i = ret[1] + 1; i < ret[2]; i++) {
        std::cout << "[" << i << "] " << arr[i].first << " " << arr[i].second << std::endl;
    }

}
int main() {

    testfloat();
    std::cout << "-----------------------------------\n";
    testbool();

    return 0;
}

floatの場合

 

分割前の配列:
[0] 3.7 a
[1] 2.3 b
[2] 7.5 c
[3] 1.2 d
[4] 6.8 e
[5] 5.6 f
[6] 2.4 g
[7] 0.9 h
[8] 6.1 i
[9] 5.3 j
[10] 4.5 k
[11] 8.2 l
[12] 9.1 m
[13] 1.7 n
[14] 5.3 o
[15] 7.7 p
[16] 3.8 q
[17] 4.2 r
ピボット: [9]5.3 j
分割後の配列:
[0] 3.7 a
[1] 2.3 b
[2] 4.2 r
[3] 1.2 d
[4] 3.8 q
[5] 5.3 o
[6] 2.4 g
[7] 0.9 h
[8] 1.7 n
[9] 4.5 k

[10] 5.3 j

[11] 8.2 l
[12] 9.1 m
[13] 6.1 i
[14] 5.6 f
[15] 7.7 p
[16] 6.8 e
[17] 7.5 c

 

Boolの例

 

分割前の配列:
[0] 1 a
[1] 0 b
[2] 0 c
[3] 1 d
[4] 1 e
[5] 1 f
[6] 0 g
[7] 1 h
[8] 0 i
[9] 1 j
ピボット: [5]1 f
分割後の配列:
[0] 1 a
[1] 1 j
[2] 1 h
[3] 1 d
[4] 1 e

[5] 1 f

[6] 0 g
[7] 0 c
[8] 0 i
[9] 0 b

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: