C++标准模板库编程实战 第六章 排序、合并、搜索和分区

目录

6.1 序列排序

6.1.1 排序以及相等元素的排序

6.1.2 部分排序:

6.1.3 测试排序序列

6.2 合并序列

6.3 搜索序列中的对象


6.1 序列排序

1.sort()默认将元素段升序,所以排序的对象类型需要支持<运算符。

Iter是元素段对应的迭代器类型,必须支持随机访问迭代器。所以sort()只接受array,vector,deque或标准数组。

可以提供一个用于比较元素的函数对象,作为sort第三个参数,这个比较函数必须返回bool值,而且有两个参数:

std::deque words {"one", "two", "nine", "nine", "one", "three", "four", "five", "six"};
std::sort(std::begin(words), std::end(words),
 [](const string& s1, const string& s2){ return s1.back() > s2.back(); });
std::copy(std::begin(words), std::end(words),
 std::ostream_iterator {std::cout, " "}); // six four two one nine nine one three five

6.1.1 排序以及相等元素的排序

对元素进行排序且不改变相等元素的顺序:

stable_sort()

6.1.2 部分排序:

1.partial_sort(),需要三个随机访问迭代器作为参数,不会保持未排序元素的顺序。

partial_sort(first,second,third):对[first,third)范围上,[first,second)包含[first,third)降序范围内最小的second-first个元素:

size_t count {5}; // Number of elements to be sorted
std::vector numbers {22, 7, 93, 45, 19, 56, 88, 12, 8, 7, 15, 10};
std::partial_sort(std::begin(numbers), std::begin(numbers) + count, std::end(numbers))

也可以提供一个函数对象作为额外参数。

2.partial_sort_copy(),四个参数:前两个指定排序应用范围,后两个是标识存放结果位置的迭代器。目的位置的元素个数决定了被排序元素个数。

std::vector numbers {22, 7, 93, 45, 19, 56, 88, 12, 8, 7, 15, 10};
size_t count {5}; // Number of elements to be sorted
std::vector result(count); // Destination for the results - count elements
std::partial_sort_copy(std::begin(numbers), std::end(numbers), std::begin(result), 
std::end(result));
std::copy(std::begin(numbers), std::end(numbers), std::ostream_iterator {std::cout, " "});
std::cout << std::endl;
std::copy(std::begin(result), std::end(result), std::ostream_iterator {std::cout, " "});
std::cout << std::endl;

原始容器中的元素顺序不会被打乱。

3.nth_element() 算法。

应用范围由第一个和第三个元素指定。第二个元素是指向第n个元素的迭代器。

将第N个元素左边都小于他,右边都大于它。

#include
#include
#include
using namespace std;
int main() {
		std::vector numbers{ 22, 7, 93, 45, 19, 56, 88, 12, 8, 7, 15, 10 };
		size_t count{ 5 }; // Index of nth element
		//std::nth_element(std::begin(numbers), std::begin(numbers) + count, std::end(numbers));
		copy(begin(numbers), end(numbers), ostream_iterator(cout, " "));
		std::nth_element(std::begin(numbers), std::begin(numbers) + count, std::end(numbers),
			std::greater<>());
		copy(begin(numbers), end(numbers), ostream_iterator(cout, " "));
		return 0;
}

6.1.3 测试排序序列

1. is_sorted() 如果范围内元素是升序的,返回true。迭代器至少应该是正向迭代器:

std::vector numbers {22, 7, 93, 45, 19};
std::vector data {1.5, 2.5, 3.5, 4.5};
std::cout << "numbers is "
 << (std::is_sorted(std::begin(numbers), std::end(numbers)) ? "": "not ")
 << "in ascending sequence.\n";
std::cout << "data is "
 << (std::is_sorted(std::begin(data), std::end(data)) ? "": "not ")
 << "in ascending sequence." << std::endl;

也可以指定函数对象:

std::cout << "data reversed is "
 << (std::is_sorted(std::rbegin(data), std::rend(data), std::greater<>()) ? "": "not ")
 << "in descending sequence." << std::endl;

2.函数模板 is_sorted_until() 判断是否升序。返回指向元素中升序序列上边界元素的迭代器。

std::vector pets {"cat", "chicken", "dog", "pig", "llama", "coati", "goat"};
std::cout << "The pets in ascending sequence are:\n";
std::copy(std::begin(pets), std::is_sorted_until(std::begin(pets), std::end(pets)),
 std::ostream_iterator{std::cout, " "});

也可以指定函数对象:

std::vector pets {"dog", "coati", "cat", "chicken", "pig", "llama", "goat"};
std::cout << "The pets in descending sequence are:\n";
std::copy(std::begin(pets),
 std::is_sorted_until(std::begin(pets), std::end(pets), std::greater<>()),
 std::ostream_iterator{std::cout, " "});

6.2 合并序列

合并操作合并两个顺序相同的序列。

1.merge()算法

5个参数:前两个第一段序列范围,中间两个第二段序列范围,最后一个是存放位置的迭代器。

返回指向合并序列末尾的后一个位置,所以可以通过第五个参数和返回的迭代器确定合并序列的范围。

也可以提供第六个参数作为其他比较方法的函数对象。

保存结果的迭代器是一个输出迭代器,也可以插入迭代器。

std::vector these {2, 15, 4, 11, 6, 7}; // 1st input to merge
std::vector those {5, 2, 3, 2, 14, 11, 6}; // 2nd input to merge
std::stable_sort(std::begin(these), std::end(these), // Sort 1st range in...
 std::greater<>()); // ...descending sequence
std::stable_sort(std::begin(those), std::end(those), // Sort 2nd range
 std::greater<>());
std::vector result(these.size() + those.size() + 10); // Plenty of room for results
auto end_iter = std::merge(std::begin(these), std::end(these), // Merge 1st range...
 std::begin(those), std::end(those), // ...and 2nd range...
 std::begin(result), std::greater<>()); // ...into result
std::copy(std::begin(result), end_iter, std::ostream_iterator{std::cout, " "});

 2.inplace_merge()可以合并同一个序列中两个连续有序的序列。

三个参数:first,second,last。[first,second)[second,last)

C++标准模板库编程实战 第六章 排序、合并、搜索和分区_第1张图片

6.3 搜索序列中的对象

6.3.1 三种在输入迭代器范围内查找单个对象的算法

1.find()前两个参数之间的范围内查找和第三个参数相等的第一个对象。

std::vector numbers {5, 46, -5, -6, 23, 17, 5, 9, 6, 5};
int value {23};
auto iter = std::find(std::begin(numbers), std::end(numbers), value);
if(iter != std::end(numbers)) std::cout << value << " was found.\n";

2.find_if() 在前两个参数指定的范围内查找可以使第三个参数指定的谓词返回true 的第一个对象。谓词不能修改传给他的对象。

int value {5};
auto iter1 = std::find_if(std::begin(numbers), std::end(numbers), 
 [value](int n) { return n > value; });
if(iter1 != std::end(numbers)) std::cout << *iter1 << " was found greater than " << value << ".\n";

3.find_if_not() 前两个参数指定范围内查找可以使第三个参数指定的谓词返回false的第一个对象。谓词不能修改传给他的对象。

size_t count {};
int five {5};
auto start_iter = std::begin(numbers);
auto end_iter = std::end(numbers);
while((start_iter = std::find_if_not(start_iter, end_iter,
 [five](int n) {return n > five; })) != end_iter)
{
 ++count;
 ++start_iter;
}
std::cout << count << " elements were found that are not greater than "<< five << std::endl;

6.3.2 查找任意范围的元素

1.find_first_of() 在第一个序列中搜索第二个序列在第一个序列中第一次出现的任何元素。

用==运算符比较这两个序列中的元素,所以如果序列中的元素是类对象,类需要实现operator==().

string text {"The world of searching"};
string vowels {"aeiou"};
auto iter = std::find_first_of(std::begin(text), std::end(text), std::begin(vowels),
 std::end(vowels));
if(iter != std::end(text)) std::cout << "We found '" << *iter << "'." << std::endl; // We found 'e'.

可以使用循环来查找text中匹配vowels的所有字符。

string found {}; // Records characters that are found
for(auto iter = std::begin(text);
 (iter = std::find_first_of(
 iter, std::end(text), std::begin(vowels), std::end(vowels))) != std::end(text); )
 found += *(iter++);
std::cout << "The characters \"" << found << "\" were found in text." << std::endl;

可以选择函数对象进行比较:

std::vector numbers {64L, 46L, -65L, -128L, 121L, 17L, 35L, 9L, 91L, 5L};
int factors[] {7, 11, 13};
auto iter = std::find_first_of(std::begin(numbers), 
 std::end(numbers), // The range to be searched
 std::begin(factors), std::end(factors), // Elements sought
 [](long v, long d) { return v % d == 0;}); // Predicate - true for a match
 if(iter != std::end(numbers)) std::cout << *iter << " was found." << std::endl

6.3.3 查找多个元素

adjacent_find() 搜索序列中两个连续相等的元素:

string saying {"Children should be seen and not heard."};
auto iter = std::adjacent_find(std::begin(saying), std::end(saying));
if(iter != std::end(saying))
 std::cout << "In the following text:\n\"" << saying << "\"\n'"
 << *iter << "' is repeated starting at index position "
 << std::distance(std::begin(saying), iter) << std::endl;

也可以自定义比较函数:

std::vector numbers {64L, 46L, -65L, -128L, 121L, 17L, 35L, 9L, 91L, 5L};
auto iter = std::adjacent_find(std::begin(numbers), std::end(numbers),
 [](long n1, long n2){ return n1 % 2 && n2 % 2; });
if(iter != std::end(numbers))
 std::cout << "The first pair of odd numbers is "
 << *iter << " and " << *(iter+1) << std::endl;

1.find_end() 在一个序列中查找最后一个和另一个元素段匹配的匹配项,也可以看作是在一个元素序列中查找子序列的最后一个匹配项。

返回指向子序列最后一个匹配项的第一个元素的迭代器。或者指向序列接受的迭代器:

string text {"Smith, where Jones had had \"had\", had had \"had had\"."
 " \"Had had\" had had the examiners\' approval."};
std::cout << text << std::endl;
 string phrase {"had had"};
 auto iter = std::find_end(std::begin(text), std::end(text), std::begin(phrase), std::end(phrase));
 if(iter != std::end(text))
 std::cout << "The last \"" << phrase
 << "\" was found at index " << std::distance(std::begin(text), iter) << std::endl;

另一个版本的find_end()接受比较元素的二元谓词作为第五个参数:

size_t count {};
auto iter = std::end(text);
auto end_iter = iter;
while((iter = std::find_end(std::begin(text), end_iter, std::begin(phrase),
 std::end(phrase))) != end_iter)
{
 ++count;
 end_iter = iter;
}
std::cout << "\n\""<< phrase << "\" was found " << count << " times." << std::endl;

2. search() 

和find_end()类似,但找的是第一个匹配项:

string text {"Smith, where Jones had had \"had\", had had \"had had\"."
 " \"Had had\" had had the examiners\' approval."};
std::cout << text << std::endl;
string phrase {"had had"};
size_t count {};
auto iter = std::begin(text);
auto end_iter = end(text);
while((iter = std::search(iter, end_iter, std::begin(phrase), std::end(phrase),
 [](char ch1, char ch2){ return std::toupper(ch1) == std::toupper(ch2); })) != end_iter)
{
 ++count;
 std::advance(iter, phrase.size()); // Move to beyond end of subsequence found
}
 std::cout << "\n\""<< phrase << "\" was found " << count << " times." << std::endl;

3.search_n() 搜索给定元素的匹配项,在序列中连续出现了给定的次数:

std::vector values {2.7, 2.7, 2.7, 3.14, 3.14, 3.14, 2.7, 2.7};
double value {3.14};
int times {3};
auto iter = std::search_n(std::begin(values), std::end(values), times, value);
if(iter != std::end(values))
 std::cout << times << " successive instances of " << value
 << " found starting index " << std::distance(std::begin(values), iter) 
<< std::endl;

6.4 分区序列

partition() 所有使给定谓词返回true的元素都放在使谓词返回false的后面。

前两个参数使范围,第三个参数是一个谓词。前两个参数是正向迭代器。

std::vector temperatures {65, 75, 56, 48, 31, 28, 32, 29, 40, 41, 44, 50};
std::copy(std::begin(temperatures), std::end(temperatures), // List the values
 std::ostream_iterator{std::cout, " "});
std::cout << std::endl;
auto average = std::accumulate(std::begin(temperatures), // Compute the average value
 std::end(temperatures), 0.0)/ temperatures.size();
std::cout << "Average temperature: " << average << std::endl;
std::partition(std::begin(temperatures), std::end(temperatures), // Partition the values
 [average](double t) { return t < average; });
std::copy(std::begin(temperatures), std::end(temperatures), // List the values after partitioning
 std::ostream_iterator{std::cout, " "});
std::cout << std::endl;

partition()算法不保证维持序列原始元素的相对顺序。

stable_partition()可以维持相对顺序,参数与partition相同。

6.4.1 partition_copy()

partition_copy()和 stable_partition()以相同的方式对序列进行分区。

但使谓词返回true的元素会被复制到一个单独的序列中,使谓词返回false的元素会被复制到第三个序列中。

操作不会改变元素序列:前两个参数确定元素序列,必须是输入迭代器,第三个参数确定目的序列的开始位置,第四个参数确定另一个目的序列的开始位置,第五个参数是用来分区的谓词。

// Ex6_04.cpp
// Using partition_copy() to find values above average and below average
#include  // For standard streams
#include  // For vector container
#include  // For partition_copy(), copy()
#include  // For accumulate()
#include  // For back_inserter, ostream_iterator
int main()
{
 std::vector temperatures {65, 75, 56, 48, 31, 28, 32, 29, 40, 41, 44, 50};
 std::vector low_t; // Stores below average temperatures
 std::vector high_t; // Stores average or above temperatures
 auto average = std::accumulate(std::begin(temperatures),std::end(temperatures), 0.0) /
 temperatures.size();
 std::partition_copy(std::begin(temperatures), std::end(temperatures),
 std::back_inserter(low_t), std::back_inserter(high_t),
 [average](double t) { return t < average; });
 // Output below average temperatures
 std::copy(std::begin(low_t), std::end(low_t), std::ostream_iterator{std::cout, " "});
 std::cout << std::endl;
 // Output average or above temperatures
 std::copy(std::begin(high_t), std::end(high_t), std::ostream_iterator{std::cout, " "});
 std::cout << std::endl;

6.4.2 partition_point()

获取分区序列中第一个分区的结束迭代器,前两个参数定义检查范围的正向迭代器,最后一个参数是用来分区的谓词。

这个算法可以使我们访问和提取这些分区中的元素。

std::vector temperatures {65, 75, 56, 48, 31, 28, 32, 29, 40, 41, 44, 50};
auto average = std::accumulate(std::begin(temperatures), // Compute the average value
 std::end(temperatures), 0.0)/ temperatures.size();
auto predicate = [average](double t) { return t < average; };
std::stable_partition(std::begin(temperatures), std::end(temperatures), predicate);
auto iter = std::partition_point(std::begin(temperatures), std::end(temperatures), predicate);
std::cout << "Elements in the first partition: ";
std::copy(std::begin(temperatures), iter, std::ostream_iterator{std::cout, " "});
std::cout << "\nElements in the second partition: ";
std::copy(iter, std::end(temperatures), std::ostream_iterator{std::cout, " "});
std::cout << std::endl;

在使用partition_point()之前,需要确定序列是否分区。

可以使用is_partitioned()来判断。参数一个是指定序列的输入迭代器,一个是用来分区的谓词。

6.5 二分查找

二分查找比一般的查找快,但要求序列是有序的。

6.5.1 binary_search()

在前两个参数范围内搜索等于第三个参数的元素,元素必须用<运算符能比较。

不会告诉我们位置,使用 lower_bound()、upper_bound 或equal_range()获取位置。

std::list values {17, 11, 40, 36, 22, 54, 48, 70, 61, 82, 78, 89, 99, 92, 43};
values.sort(); // Sort into ascending sequence
int wanted {22}; // What we are looking for
if(std::binary_search(std::begin(values), std::end(values), wanted))
 std::cout << wanted << " is definitely in there - somewhere..." << std::endl;
else
 std::cout << wanted << " cannot be found - maybe you got it wrong..." << std::endl;

可以指定比较函数,但是必须和用于被查找序列进行排序的比较操作是相同的效果。

6.5.2 lower_bound() upper_bound()

lower_bound()在前两个参数指定范围内查找不小于第三个参数的第一个元素。upper_bound()相反。所查找序列必须有序。假定使用<运算符。

也可以自定义比较函数。

6.5.3 equal_range()

找到有序序列中所有和给定元素相等的元素。

算法返回pair对象,其中first指向的是不小于第三个参数的一个元素,second指向大于第三个参数的一个元素。

也可以自定义比较函数。

std::list values{ 17, 11, 40, 36, 22, 54, 48, 70, 61, 82, 78, 89, 99, 92, 43 };
	// Output the elements in original order
	std::copy(std::begin(values), std::end(values), std::ostream_iterator {std::cout, " "});
	std::cout << std::endl;
	int wanted{ 22 }; // What we are looking for
	std::partition(std::begin(values), std::end(values), // Partition the values wrt value < wanted
		[wanted](double value) { return value < wanted; });
	std::partition(std::begin(values), std::end(values), // Partition the values wrt !(wanted < value)
		[wanted](double value) { return !(wanted < value); });
	// Output the elements after partitioning
	std::copy(std::begin(values), std::end(values), std::ostream_iterator {std::cout, " "});
	std::cout << std::endl;

	auto pr = std::equal_range(std::begin(values), std::end(values), wanted);
	std::cout << "the lower bound for " << wanted << " is " << *pr.first << std::endl;
	std::cout << "the upper bound for " << wanted << " is " << *pr.second << std::endl;

课后练习

pe6_1:参考pe5_1。

pe6_2: //merge有问题,insert没问题。

C++11,14不支持set的merge,C++17提供了,

for (int i = 0; i < 4; i++) {
        result.merge(AA[i]);
    }
#include
#include
#include
#include
#include
#include
enum class Color { red1, red2, black1, black2 };
static const std::string scolor[4] = { "red1", "red2", "black1", "black2" };
//const string scolor[4] = { "red1", "red2", "black1", "black2" };
using namespace std;

template
T generate_rand(const T& min, const T& max);
class Card {
private:
    Color color;
    int number;
public:
    //Card() :color(Color::red1), number(0) {};
    Card(Color cc, int nn) :color(cc), number(nn) {};
    Color get_color() { return color; };
    int get_number() { return number; };
    bool operator<(const Card& cc) const {
        return color < cc.color || (color == cc.color && number < cc.number);
    }
    friend std::ostream& operator<<(ostream& os, const Card& cc) {
        //static const string scolor[4] = { "red1", "red2", "black1", "black2" };
        os << scolor[int(cc.color)] << " " << cc.number << endl;
        return os;
    }
};
int main() {
    vector cc;
    set AA[4];
    
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 13; j++) {
            cc.emplace_back(static_cast(i), j);
        }
    }
    random_shuffle(begin(cc), end(cc));
    auto iter = begin(cc);
    for (int i = 0; i < 4; i++) {
        copy(iter, iter + 13, inserter(AA[i], begin(AA[i])));
        advance(iter, 13);
    }

    for (int i = 0; i < 4; i++) {
        cout << "玩家" << i << " : " << endl;
        for (auto value : AA[i]) {
            std::cout << value << endl;
        }
    }
    /*set result;
    auto iter2 = begin(result);
    merge(begin(AA[0]), end(AA[0]), begin(AA[1]), end(AA[1]), iter2);
    advance(iter2, 26);
    merge(begin(AA[2]), end(AA[2]), begin(AA[3]), end(AA[3]), iter2);
    for (auto value : result) {
        cout << value << endl;
    }*/
    std::set result;
    for (int i = 0; i < 2; i++) {
        result.insert(AA[i].begin(), AA[i].end());
    }
    for (int i = 2; i < 4; i++) {
        result.insert(AA[i].begin(), AA[i].end());
    }
    std::cout << "show all: " << std::endl;
    for (const auto& value : result) {
        std::cout << value << std::endl;
    }
    return 0;
}
template
T generate_rand(const T& min, const T& max) {
    // 创建一个随机数引擎
    std::random_device rd;
    std::mt19937 gen(rd());

    // 定义随机数的范围
    /*int min = 1;
    int max = 52;*/

    // 创建一个分布对象,指定随机数的范围
    std::uniform_int_distribution<> dis(min, max);

    // 生成随机数
    /*int random_num = dis(gen);*/
    return dis(gen);
}

pe6_3:

#include
#include
#include
#include
#include
using namespace std;
enum class Color { black, grey,  grown, gold};
const string hair[4] = { "black", "grey",  "grown", "gold" };
class Person {
private:
	string name;
	Color color;
public:
	Person(string nn, Color cc) :name(nn), color(cc) {};
	Person(string nn, int cc) :name(nn), color(static_cast(cc)) {};
	string get_name() { return name; };
	Color get_color() { return color; };
	bool operator<(const Person& pp) {

		return color < pp.color;
	}
	friend ostream& operator<<(ostream&  os, const Person& pp) {
		os << "名字:" << pp.name << " 头发颜色:" << hair[static_cast(pp.color)] << endl;
		return os;
	}
};

int generate_hair(int min = 0, int max = 3);
int main() {
	vector people;
	string name;
	cout << "Enter people's name.Enter ctrl+Z on a new line to end:\n";
	while (true)
	{
		if ((cin >> name).eof()) {
			cin.clear();
			break;
		}
		people.push_back({ name,generate_hair()});
	}
	cout << "show all: " << endl;
	for (auto value : people) {
		cout << value << endl;;
	}
	cout << "show grey: " << endl;
	std::partition(begin(people), end(people), [](Person pp) {return pp.get_color() dis(min, max);
	return dis(gen);
}

pe6_4:

自定义类内比较函数不加static 报错(改为全局函数也行):

愿意:查看sort源码(文末会贴出)会发现,sort的第三个参数,也就是我们自定义的cmp,只允许接收两个参数,而当在类内定义cmp函数时,如果像上述那样定义,在编译时,编译器会向函数添加隐式参数this,而变成了三个参数,所以编译会报错。

参考:类内sort自定义排序函数需定义为static否则报错_ccJun-的博客-CSDN博客 

#include
#include
#include
#include
#include
using namespace std;
enum class Color { black, grey, brown, gold };
const string hair[4] = { "black", "grey",  "brown", "gold" };
class Person {
private:
	string name;
	Color color;
public:
	Person(string nn, Color cc) :name(nn), color(cc) {};
	Person(string nn, int cc) :name(nn), color(static_cast(cc)) {};
	string get_name() { return name; };
	Color get_color() { return color; };
	bool static com_name(const Person& pp1, const Person& pp2) {

		return pp1.name < pp2.name;
	}
	
	bool operator<(const Person& pp) {

		return color < pp.color;
	}
	friend ostream& operator<<(ostream& os, const Person& pp) {
		os << "名字:" << pp.name << " 头发颜色:" << hair[static_cast(pp.color)] << endl;
		return os;
	}
};

int generate_hair(int min = 0, int max = 3);
int main() {
	vector people;
	string name;
	cout << "Enter people's name.Enter ctrl+Z on a new line to end:\n";
	while (true)
	{
		if ((cin >> name).eof()) {
			cin.clear();
			break;
		}
		people.push_back({ name,generate_hair() });
	}
	
	cout << "show all: " << endl;
	for (auto value : people) {
		cout << value << endl;;
	}
	sort(begin(people), end(people), Person::com_name);
	cout << "After sort name: " << endl;
	for (auto value : people) {
		cout << value << endl;;
	}

	sort(begin(people), end(people));
	cout << "After sort color: " << endl;
	for (auto value : people) {
		cout << value << endl;;
	}
	//std::partition(begin(people), end(people), [](Person pp) {return pp.get_color() < Color::grey; });
	///*for (auto value : people) {
	//	cout << value << endl;;
	//}*/
	//std::partition(begin(people), end(people), [](Person pp) {return pp.get_color() < Color::brown; });

	cout << "Partition color: " << endl;
	auto iter1 = partition_point(begin(people), end(people), [](Person pp) {return pp.get_color() < Color::grey; });
	auto iter2 = partition_point(begin(people), end(people), [](Person pp) {return pp.get_color() < Color::brown; });
	auto iter3 = partition_point(begin(people), end(people), [](Person pp) {return pp.get_color() < Color::gold; });


	copy(begin(people), iter1, ostream_iterator(cout, ""));
	copy(iter1, iter2, ostream_iterator(cout, ""));
	copy(iter2, iter3, ostream_iterator(cout, ""));
	copy(iter3, end(people), ostream_iterator(cout, ""));



	return 0;
}
int generate_hair(int min, int max) {
	std::random_device rd;
	std::mt19937 gen(rd());

	std::uniform_int_distribution<> dis(min, max);
	return dis(gen);
}

 pe6_5:

按照给定序列的顺序进行排序使用find()获取位置信息,然后在比较函数中比较find返回的迭代器位置。

#include
#include
#include
#include
#include
using namespace std;
enum class Color { black, grey, brown, gold };
const string hair[4] = { "black", "grey",  "brown", "gold" };
class Name
{
private:
	static string sequence ;
	std::string first{};
	std::string second{};
public:
	Name(const std::string& name1, const std::string& name2) :
		first(name1), second(name2) {}
	Name() = default;
	// Less-than operator
	bool operator<(const Name& name) const
	{
		char letter1 = toupper(first[0]);
		char letter2 = toupper(name.first[0]);
		
		auto iter1 = find(begin(sequence), end(sequence), letter1);
		auto iter2 = find(begin(sequence), end(sequence), letter2);
		return iter1>(std::istream& in, Name& name);
	friend std::ostream& operator<<(std::ostream& out, const Name& box);
};
string Name::sequence = "RWQOJMVAHBSGZXNTCIEKUPDYEL";
// Extraction operator overload
inline std::istream& operator>>(std::istream& in, Name& name)
{
	in >> name.first >> name.second;
	return in;
}
// Insertion operator overload
inline std::ostream& operator<<(std::ostream& out, const Name& name)
{
	out << name.first + " " + name.second << endl;
	return out;
}

int generate_hair(int min = 0, int max = 3);
int main() {
	
	std::vector names = {
	{"Joe"," Yodel"},
	{"Bob"," Zippo"},
	{"Alice"," Smith"},
	{"Robert"," Johnson"},
	// Add more names as needed
	};


	stable_sort(begin(names), end(names));
	copy(begin(names), end(names), ostream_iterator(cout, ""));
	return 0;
}
int generate_hair(int min, int max) {
	std::random_device rd;
	std::mt19937 gen(rd());

	std::uniform_int_distribution<> dis(min, max);
	return dis(gen);
}

你可能感兴趣的:(c++,算法,数据结构)