STL forward_list 单向链表

什么是链表?
链表是由一些列节点组成的,每一个阶段包含数据域、指针域,每个节点的内存都是独立,使用的是非连续的内存。 链表分为:单向链表、双向链表、循环链表
单向链表的开销最低,空间只需要一个指针即可,从操作角度:单向链表添加或者删除元素时候只需要维护一个指针,而双向链表需要维护两个。

链表优缺点
链表优点是:添加或者删除链表中的元素,不需要移动其他的元素。
链表缺点是:不支持下标,根据位置查找元素的话效率低。

链表的迭代器
链表添加和删除元素都不会导致空间重新配置,所以,指向原来数据的迭代器不会因为添加或者删除元素而失效。除非删除的是迭代器指向的元素。

forward_list 属于单向链表,不支持反向遍历的。没有 reverse 迭代器。

下面示例代码主要从以下几个方面来讲解 forward_list 容器:

  1. 创建和大小
  2. 添加元素
  3. 删除元素
  4. 拼接元素
  5. 排序操作
  6. 内建函数对象
  7. 合并有序链表
// 1. 创建和大小
void test01()
{
	// forward list 叫做前向的单向链表
	forward_list<int> fl = { 10, 20, 30, 40 };
	cout << fl.max_size() << endl;
	// forward_list 不提供 size 函数
	// 为什么 forward_list 不提供 size 函数?
	// 认为 size 函数会影响效率。
	// 1. 类内部维护一个变量 size, 每次添加和删除元素的时候都需要维护该变量。
	// 2. 类内部不维护用于记录大小的变量,每次调用 size 函数时,从头到尾数一遍即可。

	// 如果我要想知道链表中元素的个数,应该怎么办?
	// 1. 自己遍历下链表,数一数节点的个数。
	// 2. distance 函数计算下链表中元素的个数
	cout << distance(fl.begin(), fl.end()) << endl;
}

// 2. 添加元素
class Person
{
public:
	Person(string name, int age)
	{
		m_name = name;
		m_age = age;
	}

	bool operator<(const Person& person) const
	{
		return m_age < person.m_age;
	}

public:
	string m_name;
	int m_age;
};

void test02()
{
	forward_list<Person> fp;

	// insert_after(位置,元素) 在指定位置的后面添加一个元素
	// begin 返回的是第一个元素的位置
	// before_begin 返回的是第一个元素前面的位置(虚拟位置)
	fp.insert_after(fp.before_begin(), Person("Smith", 20));

	// push_front, 没有 push_back, 在链表头部添加元素
	fp.push_front(Person("Polly", 30));

	// emplace_front  在链表的头部添加元素
	// emplace_front 使用传递的参数构建一个 Person 对象,然后存储到指定位置。
	fp.emplace_front("Obama", 40);

	// emplace_after  在指定的位置后面添加元素
	fp.emplace_after(fp.begin(), "Edward", 50);


	for (forward_list<Person>::iterator it = fp.begin(); it != fp.end(); ++it)
	{
		cout << it->m_name << " " << it->m_age << endl;
	}
}


// 3. 删除元素
void test03()
{
	forward_list<int> fl = { 10, 20, 30, 30, 40, 50 };
	// erase_after 删除某个位置之后的元素
	// 删除指定位置后面的元素
	// fl.erase_after(fl.begin());
	// fl.pop_front();
	// fl.erase_after(fl.before_begin());

	// 删除指定区间的元素,第一个位置不包括
	// fl.erase_after(fl.before_begin(), fl.end());

	// 按值删除 : 删除容器中所有该值的元素。
	// fl.remove(30);
	// 删除满足某些条件的元素,条件是包含一个参数的,返回值为布尔类型的普通函数、函数对象、匿名函数对象。
	// fl.remove_if([](int val) { return val >= 30; });

	// 删除所有的元素
	fl.clear();

	for (forward_list<int>::iterator it = fl.begin(); it != fl.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

}

// 4. 拼接元素
void test04()
{
	// 拼接:将一个链表元素添加到另外一个链表中
	forward_list<int> f1 = { 10, 20, 30 };
	forward_list<int> f2 = { 100, 200, 300 };

	// 在指定位置的后面拼接新的数据
	// f1.splice_after(f1.begin(), f2);
	// f1.splice_after(f1.before_begin(), f2);

	// splice_after 将 f2 中指定位置后面的元素添加到 f1 中
	// f1.splice_after(f1.before_begin(), f2, f2.before_begin());

	// 区间不包含两侧元素的。也就是将指定区间之间的所有元素拼接到 f1 指定位置的后面
	f1.splice_after(f1.before_begin(), f2, f2.begin(), f2.end());

	for (forward_list<int>::iterator it = f1.begin(); it != f1.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}


// 5. 排序操作
void test05()
{
	forward_list<int> f = { 80, 50, 40, 70, 60, 20, 30 };
	// 使用 sort 函数排序
	// 默认进行升序排列。
	// 要使用 sort 排序,存储的元素必须支持 operator< 比较。
	// f.sort();

	// 指定降序排序(从大到小)
	// f.sort([](int v1, int v2) { return v1 > v2; });
	f.sort(greater<int>());

	for (forward_list<int>::iterator it = f.begin(); it != f.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test06()
{
	forward_list<Person> f = { Person("aaa", 60), Person("aaa", 20) , Person("aaa", 70), Person("aaa", 50) };
	// 升序排列
	// f.sort();
	// 降序排列
	f.sort([](Person &v1, Person &v2) { return v1.m_age > v2.m_age; });

	for (forward_list<Person>::iterator it = f.begin(); it != f.end(); ++it)
	{
		cout << it->m_name << " " << it->m_age << endl;
	}
}

// 6. 内建函数对象
// C++ 标准库提供了很多常用的函数对象,算术运算类、比较运算类、逻辑运算类

void test07()
{
	// 算术运算类
	cout << plus<int>()(10, 20) << endl;
	cout << minus<int>()(10, 20) << endl;
	cout << divides<int>()(10, 20) << endl;
	cout << multiplies<int>()(10, 20) << endl;

	// 比较运算类
	cout << less<int>()(10, 20) << endl;
	cout << less_equal<int>()(10, 20) << endl;
	cout << equal_to<int>()(10, 20) << endl;
	cout << not_equal_to<int>()(10, 20) << endl;
	cout << greater<int>()(10, 20) << endl;
	cout << greater_equal<int>()(10, 20) << endl;

	// 逻辑运算类
	cout << logical_and<int>()(10 > 20, 20 > 30) << endl;
	cout << logical_or<int>()(10 > 20, 20 > 30) << endl;
	cout << logical_not<int>()(10 > 20) << endl;
}

// 7. 合并有序链表
void test08()
{
	forward_list<int> f1 = { 80, 50, 40, 70, 60, 20, 30 };
	forward_list<int> f2 = { 30, 40, 20, 90 };

	f1.sort(greater<int>());
	f2.sort(greater<int>());
	// 合并两个有序链表,最终合并的结果依然保持有序
	// 如果合并的两个有序序列并不是升序的。
	f1.merge(f2, greater<int>());

	for (forward_list<int>::iterator it = f1.begin(); it != f1.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
未经允许不得转载:一亩三分地 » STL forward_list 单向链表
评论 (0)

6 + 9 =