C++泛型编程(2)--通过排序和查找元素理解迭代器

许多C++开源库(stl,opencv,ros和blas等)都使用了大量的泛型编程的思想,如果不理解这些思想,将很难看懂代码,而《泛型编程与STL》一书对理解泛型编程思想非常的有帮助,这里整理第二章的一些实现代码。

1.排序元素

#include <iostream>
#include <vector>
#include <algorithm>
#include <ostream>
#include <iterator>
using namespace std;

int main(int argc, char** argv)
{
  vector<string> V;
  string tmp;

  while (getline(cin, tmp))
  {
    if (tmp == "")
      break;  // 回车结束
    V.push_back(tmp);
  }
  // sort(V.begin(), V.end());// 升序
  sort(V.begin(), V.end(), greater<string>());  // 降序
  copy(V.begin(), V.end(), ostream_iterator<string>(cout, "\n"));
  return 0;
}

运行结果

输入:
1
2
3
4
5
6
7

排序输出:
7
6
5
4
3
2
1

 

 

2.查找元素

#include <string.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <ostream>
#include <iterator>
using namespace std;

// 通常的查找方法,通过'\0'来结束查找
char* strchr(char *s, int c)
{
  while (*s != '\0' && *s != c)
  {
    ++s;
  }
  return *s == c ? s : (char*) 0;  // #define NULL (char*) 0
}

// C 改进版本的查找方法,引入了range的概念[first, last),
// 通过比较指针first = last来结束查找
char* find1(char* first, char* last, int value)
{
  while (first != last && *first != value)
    ++first;
  return first;
}

// C++ 模板方法查找,数据类型作为模板参数传入
template<class T>
T* find2(T* first, T* last, T value)
{
  while (first != last && *first != value)
    ++first;
  return first;
}

// C++ 模板方法查找,访问器和数据类型都作为模板参数传入,
// 相较于find2,find具有更一般性。其很好地解决了以下问题:
// 1.审视元素;2.移动到下一个元素;3.检查是否已经处理完成所有元素;4.元素比较
template<class Iterator, class T>
Iterator find3(Iterator first, Iterator last, const T& value)
{
  while (first != last && *first != value)
  {
    ++first;
  }
  return first;
}

// 链表查找
struct int_node
{
  int value;
  int_node* next;
};

// 链表无法满足 操作符的比较,因此通过一个外覆类实现++ == ->等操作符号的重载
template<class Node>
struct node_wrapper
{
  Node* ptr;
  node_wrapper(Node* p = 0)
      : ptr(p)
  {
  }
  // *
  Node& operator *() const
  {
    return *ptr;
  }
  // 访问->
  Node* operator ->() const
  {
    return ptr;
  }
  // 前置累加
  node_wrapper operator++()
  {
    ptr = ptr->next;

    return *this;
  }
  // 后置累加
  node_wrapper operator ++(int)
  {
    node_wrapper tmp = *this;
    ++*this;
    return tmp;
  }
  // 相等判断
  bool operator ==(const node_wrapper& i) const
  {
    return ptr == i.ptr;
  }
  // 非相等判断
  bool operator !=(const node_wrapper& i) const
  {
    return ptr != i.ptr;
  }
};

// template funtion, object function
template<class Node, class T>
bool operator !=(const Node& node, T value)
{
  if (node.value != value)
    return true;
  return false;
}

int main(int argc, char** argv)
{
  char pat = 'x';
  char str[10] = "horsetail";
  int str_size = strlen(str);

  cout << "****Task1: to find '" << pat << "' from \"" << str << "\"" << endl;

  // 通常的查找方法,通过'\0'来结束查找
  cout << "----testing strchr----" << endl;
  char* res = strchr(str, (int) pat);  // to find
  if (res != NULL)
    cout << "found " << pat << endl;
  else
    cout << "not found " << pat << endl;

  // C 改进版本的查找方法,引入了range的概念[first, last),
  // 通过比较指针first = last来结束查找
  cout << "----testing find1----" << endl;
  res = find1(str, str + str_size, (int) pat);  // to find
  if (res != str + str_size)
    cout << "found " << pat << endl;
  else
    cout << "not found " << pat << endl;

  // C++ 模板方法查找,数据类型作为模板参数传入
  cout << "----testing find2----" << endl;
  res = find2(str, str + str_size, pat);  // to find
  if (res != str + str_size)
    cout << "found " << pat << endl;
  else
    cout << "not found " << pat << endl;

  // C++ 模板方法查找,访问器和数据类型都作为模板参数传入,
  // 相较于find2,find具有更一般性。其很好地解决了以下问题:
  // 1.审视元素;2.移动到下一个元素;3.检查是否已经处理完成所有元素;4.元素比较
  cout << "----testing find3----" << endl;
  res = find3(str, str + str_size, pat);  // to find
  if (res != str + str_size)
    cout << "found " << pat << endl;
  else
    cout << "not found " << pat << endl;

  // 链表查找,链表无法满足 操作符的比较,因此通过一个外覆类实现++ == ->等操作符号的重载
  int value = 6;
  int link_size = 10;
  cout << endl;
  cout << "****Task2: to find " << value << " from {0,1,2,3,...,10}" << endl;
  cout << "----testing link int_node with find3----" << endl;
  int_node* head_node = new int_node();
  head_node->value = 0;
  head_node->next = 0;
  int_node* pnode = head_node;
  for (int i = 1; i < link_size; i++)
  {// link contain {0,1,2,3,4,5,6,...}
    int_node* node = new int_node();
    node->value = i;
    node->next = 0;

    pnode->next = node;
    pnode = node;
  }

  node_wrapper<int_node> first(head_node);
  node_wrapper<int_node> last(0);
  node_wrapper<int_node> result = find3(first, last, value);  // to find
  if (result != last)
    cout << "found " << value << endl;
  else
    cout << "not found " << value << endl;

  return 0;
}

运行结果

****Task1: to find 'x' from "horsetail"
----testing strchr----
not found x
----testing find1----
not found x
----testing find2----
not found x
----testing find3----
not found x

****Task2: to find 6 from {0,1,2,3,...,10}
----testing link int_node with find3----
found 6

参考资料

[1].泛型编程与STL 侯捷 - 2003 - 中国电力出版社,第二章

posted @ 2017-11-03 13:55  horsetail  阅读(454)  评论(0编辑  收藏  举报