C++ 9|Containers and Iterators

9. Containers and iterators

Experts in the coding world have written many valuable libraries, containers, algorithms, etc. and made them open source, so we basically stand on the shoulders of these giants in the development of subsequent projects and large projects. I believe that many people use the library or code structure of the predecessors as the basis, and then use the knowledge we have learned to make shallow modifications (change the soup without changing the medicine), integrate functions, and finally meet their own needs. It's a bit long-winded. In short, using other people's libraries is a good way to improve efficiency.

1. Container

/********顺序容器********/
vector		list	  deque		适配器		statck		 queue		priority_queue
/********关联容器********/
map			set//tree		multimap		multiet

Example 40. Linked list implementation (C++ method)

#include <iostream>
#include <ostream>

using namespace std;

class myList{
    
    	
	struct Node{
    
    //struct声明的所有类都是public
		Node(int x, Node *ptr=NULL):data(x), next(ptr) {
    
     }
		int data;
		Node *next;
	};
public:
	myList():head(NULL) {
    
     }//初始化表,见例9
	~myList() {
    
    
		while(head)//遍历
		{
    
    
			Node *tem = head;
			head = head->next;
			delete tem;
		}
	}

	void insert_head(int data)
	{
    
    
		Node *node = new Node(data);//数据传给节点
		node->next = head;          
		head = node;
	}

    //声明成友元,见例11
	friend ostream &operator<<(ostream &out, const myList &list);
private:
	Node *head;
};

//运算符<<重载,见例21
ostream &operator<<(ostream &out, const myList &list)//&list是常引用
{
    
    
	myList::Node *tem = list.head;//Node是内部类所以要名字限定在myList
	while(tem)
	{
    
    
		out<< tem->data <<',';
		tem = tem->next;
	}
	out << endl;//输出流的out所以不是cout,ostream是标准输出流

	return out;
}

int main()
{
    
    
	myList list;

	list.insert_head(1);
	list.insert_head(2);
	list.insert_head(4);
	list.insert_head(3);

	cout << list;

}

operation result

@ubuntu:/mnt/hgfs/ub2$ g++ list1.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
3,4,2,1,
@ubuntu:/mnt/hgfs/ub2$ 

2. Iterator

Realize that the pointer p points to a node and then p+1 points to the next node

Example 41, iterator_1

#include <iostream>
#include <ostream>

using namespace std;

class myList{
    
    	
   struct Node{
    
    
   	Node(int x, Node *ptr=NULL):data(x), next(ptr) {
    
     }
   	int data;
   	Node *next;
   };
public:
   class iterator{
    
    //迭代器类,要申请为public,否则默认成私有会报错
   public:
   	iterator(Node *ptr=NULL):pos(ptr) {
    
      }//初始化表
   	iterator &operator++(int)//重载运算符++
   	{
    
    
   		if(NULL != pos)
   			pos = pos->next;
   		return *this;
   	}

   	int &operator*()
   	{
    
    
   		return pos->data;
   	}

   	bool operator!=(iterator x)
   	{
    
    
   		return pos != x.pos;
   	}
   private:
   	Node *pos;
   };
public:
   myList():head(NULL) {
    
     }
   ~myList() {
    
    
   	while(head)
   	{
    
    
   		Node *tem = head;
   		head = head->next;
   		delete tem;
   	}
   }

   void insert_head(int data)
   {
    
    
   	Node *node = new Node(data);
   	node->next = head;
   	head = node;
   }

   iterator begin()//起始迭代器
   {
    
    
   	return iterator(head);
   }
   iterator end()//尾巴迭代器
   {
    
    
   	return iterator(NULL);
   }


   friend ostream &operator<<(ostream &out, const myList &list);
private:
   Node *head;
};

ostream &operator<<(ostream &out, const myList &list)
{
    
    
   myList::Node *tem = list.head;
   while(tem)
   {
    
    
   	out<< tem->data <<',';
   	tem = tem->next;
   }
   out << endl;

   return out;
}

int main()
{
    
    
   myList list;

   list.insert_head(1);
   list.insert_head(2);
   list.insert_head(4);
   list.insert_head(3);

   cout << list;

   myList::iterator i = list.begin();//开始时获取起始迭代器
   while(i != list.end() )//判定尾巴迭代器
   {
    
    
       //重载运算符 *号和 ++号 以及 !=号
   	cout << *i <<endl;
   	i++;//遍历链表
   }

}

operation result

@ubuntu:/mnt/hgfs/ub2$ g++ list_iterator1.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
3,4,2,1,
3
4
2
1
@ubuntu:/mnt/hgfs/ub2$ 

3. STL container

template <typename T>	//类型模板化

Example 42, iterator_2

#include <iostream>
#include <ostream>

using namespace std;

template <typename T>
class myList{	
	struct Node{
		Node(T x, Node *ptr=NULL):data(x), next(ptr) { }
		T data;
		Node *next;
	};
public:
	class iterator{
	public:
		iterator(Node *ptr=NULL):pos(ptr) {  }
		iterator &operator++(int)
		{
			if(NULL != pos)
				pos = pos->next;
			return *this;
		}

		int &operator*()
		{
			return pos->data;
		}

		bool operator!=(iterator x)
		{
			return pos != x.pos;
		}
	private:
		Node *pos;
	};
public:
	myList():head(NULL) { }
	~myList() {
		while(head)
		{
			Node *tem = head;
			head = head->next;
			delete tem;
		}
	}

	void insert_head(T data)
	{
		Node *node = new Node(data);
		node->next = head;
		head = node;
	}

	iterator begin()
	{
		return iterator(head);
	}
	iterator end()
	{
		return iterator(NULL);
	}


	template <typename X>
	friend ostream &operator<<(ostream &out, const myList<X> &list);
private:
	Node *head;
};

template <typename X>
ostream &operator<<(ostream &out, const myList<X> &list)
{
	typename myList<X>::Node *tem = list.head;
	//myList<X>::Node *tem = list.head;会报错,需要typename修饰
	while(tem)
	{
		out<< tem->data <<',';
		tem = tem->next;
	}
	out << endl;

	return out;
}

int main()
{
	myList<int> list;

	list.insert_head(1);
	list.insert_head(2);
	list.insert_head(4);
	list.insert_head(3);

	cout << list;

	myList<int>::iterator i = list.begin();
	while(i != list.end() )
	{
		cout << *i <<endl;
		i++;
	}

}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ list_iterator_template.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
3,4,2,1,
3
4
2
1
@ubuntu:/mnt/hgfs/ub2$

The official has provided many containers, which can be used by directly including the header file

insert image description here

Example 43, vector_1

#include <iostream>
#include <vector>

using namespace std;

int main()
{

	vector<int> arr;

	arr.push_back(1);
	arr.push_back(2);
	arr.push_back(3);
	arr.push_back(4);
	arr.push_back(5);


	vector<int>::iterator i = arr.begin();

	while(i != arr.end() )
	{
		cout<< *i <<endl;
		i++;
	}
}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ vector_list1.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
1
2
3
4
5
@ubuntu:/mnt/hgfs/ub2$

In addition to shaping int, you can also implement floating point, such as double

Example 44, vector_2

#include <iostream>
#include <vector>

using namespace std;

int main()
{
#if 0
	vector<int> arr;

	arr.push_back(1);
	arr.push_back(2);
	arr.push_back(3);
	arr.push_back(4);
	arr.push_back(5);
#endif
	vector<double> arr;

	arr.push_back(1.2);
	arr.push_back(1.2);
	arr.push_back(1.2);
	arr.push_back(1.2);
	arr.push_back(1.2);

//	vector<int>::iterator i = arr.begin();
	vector<double>::iterator i = arr.begin();

	while(i != arr.end() )
	{
		cout<< *i <<endl;
		i++;
	}
}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ vector_list2.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
1.2
1.2
1.2
1.2
1.2
@ubuntu:/mnt/hgfs/ub2$

The following is the container list chain storage

Example 45, list

#include <iostream>
//#include <vector>
#include <list>

using namespace std;

int main()
{
#if 0
	vector<int> arr;

	arr.push_back(1);
	arr.push_back(2);
	arr.push_back(3);
	arr.push_back(4);
	arr.push_back(5);
#endif
//	vector<double> arr;
	list<double> arr;
	arr.push_back(1.2);
	arr.push_back(1.2);
	arr.push_back(1.2);
	arr.push_back(1.2);
	arr.push_back(1.2);

//	vector<int>::iterator i = arr.begin();
//	vector<double>::iterator i = arr.begin();
	list<double>::iterator i = arr.begin();
	while(i != arr.end() )
	{
		cout<< *i <<endl;
		i++;
	}
}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ vector_list3.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
1.2
1.2
1.2
1.2
1.2
@ubuntu:/mnt/hgfs/ub2$

Example 46. map

#include <iostream>
#include <map>

using namespace std;

int main()
{
	map<string, string> user_passwd;//用户名,密码
	
	user_passwd.insert(user_passwd.begin(), pair<string, string>("aaa", "1111") );
	user_passwd.insert(user_passwd.begin(), pair<string, string>("aaa4", "114411") );
	user_passwd.insert(user_passwd.begin(), pair<string, string>("aaa2", "111331") );
	user_passwd.insert(user_passwd.begin(), pair<string, string>("aaa3", "111441") );

	map<string, string>::iterator i = user_passwd.begin();
	while(i != user_passwd.end())
	{
		cout<< (*i).first<< ',' <<(*i).second <<endl;
		i++;
	}

	cout<< user_passwd["aaa2"] << endl;
    //通过用户名aaa2打印出相应的密码111331
}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ map.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
aaa,1111
aaa2,111331
aaa3,111441
aaa4,114411
111331
@ubuntu:/mnt/hgfs/ub2$

4. STL algorithm

Example 47, sorting algorithm sort

#include <iostream>
#include<algorithm>

using namespace std;

int main()
{	
	int arr[] = {1,1234,23,4,23,42,34,23,42,34,2,2,2,444,22};
	int n = sizeof(arr)/sizeof(int);

//排序前遍历一次
	for(int i = 0; i<n; i++)
		cout <<arr[i]<<',';
	cout<<endl;

	sort(arr, arr+n);
	cout<<"xxxxxxxxxxxxxxxxxxx\n";

//排序后遍历一次
	for(int i = 0; i<n; i++)
		cout <<arr[i]<<',';
	cout<<endl;

}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ algorethm1.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
1,1234,23,4,23,42,34,23,42,34,2,2,2,444,22,
xxxxxxxxxxxxxxxxxxx
1,2,2,2,4,22,23,23,23,34,34,42,42,444,1234,
@ubuntu:/mnt/hgfs/ub2$ 

There are also algorithms for loop traversal, which are represented by for_each

Example 48, traversal algorithm for_each

#include <iostream>
#include<algorithm>

using namespace std;
bool cmp(int a, int b)
{
    return a<b;
}

void show(int data)
{
    cout << data << ",";
}

int main()
{	
	int arr[] = {1,1234,23,4,23,42,34,23,42,34,2,2,2,444,22};
	int n = sizeof(arr)/sizeof(int);

//排序前遍历一次
	for_each(arr, arr+n, show);
	cout<<endl;

	sort(arr, arr+n, cmp);//排序
	cout<<"xxxxxxxxxxxxxxxxxxx\n";

//排序后遍历一次
	for_each(arr, arr+n, show);
	cout<<endl;

}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ algorethm2.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
1,1234,23,4,23,42,34,23,42,34,2,2,2,444,22,
xxxxxxxxxxxxxxxxxxx
1,2,2,2,4,22,23,23,23,34,34,42,42,444,1234,
@ubuntu:/mnt/hgfs/ub2$

Example 49, unique algorithm for deduplication

#include <iostream>
#include<algorithm>

using namespace std;
bool cmp(int a, int b)
{
    return a<b;
}

void show(int data)
{
    cout << data << ",";
}

int main()
{	
	int arr[] = {1,1234,23,4,23,42,34,23,42,34,2,2,2,444,22};
	int n = sizeof(arr)/sizeof(int);

//排序前遍历一次
	for_each(arr, arr+n, show);
	cout<<endl;

	sort(arr, arr+n, cmp);//排序
	cout<<"xxxxxxxxxxxxxxxxxxx\n";

//排序后遍历一次
	for_each(arr, arr+n, show);
	cout<<endl;

    cout<<"xxxxxxxxxxxxxxxxxxx\n";
    unique(arr, arr+n);

//除重后遍历一次
    for_each(arr, arr+n, show);
	cout<<endl;

}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ algorethm3.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
1,1234,23,4,23,42,34,23,42,34,2,2,2,444,22,
xxxxxxxxxxxxxxxxxxx
1,2,2,2,4,22,23,23,23,34,34,42,42,444,1234,
xxxxxxxxxxxxxxxxxxx
1,2,4,22,23,34,42,444,1234,34,34,42,42,444,1234,
@ubuntu:/mnt/hgfs/ub2$

Note: The length will not be automatically shortened after weight removal (the length is the same as before), and the latter will be presented as it is. For example, there are 15 numbers in the case, after the division of weights, 9 numbers appear in the front (1, 2, 4, 22, 23, 34, 42, 444, 1234,), and then the last 6 numbers are consistent with the original number (34 ,34,42,42,444,1234,)

Example 50. Algorithm find_if for finding content and count_if algorithm for obtaining the number of content

#include <iostream>
#include<algorithm>

using namespace std;

bool fnd(int data)
{
	//return data == 12345;//找不到,打印got err!
	return data == 2;//能找到,打印got success!
}

int main()
{	
	int arr[] = {1,1234,23,4,23,42,34,23,42,34,2,2,2,444,22};
	int n = sizeof(arr)/sizeof(int);

	int *p = find_if(arr, arr+n, fnd);
    
    if(p != arr+n)
    {
        cout << "got success! \n";
    }else{
        cout << "got err! \n";        
    }
    	cout <<"num of 2: "<< count_if(arr, arr+n, fnd) << endl;
}

operation result:

@ubuntu:/mnt/hgfs/ub2$ g++ algorethm4.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
got success! 
num of 2: 3
@ubuntu:/mnt/hgfs/ub2$ 

Guess you like

Origin blog.csdn.net/weixin_44035986/article/details/126257911