栈,队列,优先级队列的实现和仿函数

目录

1.认识栈和队列

2.容器适配器

3.栈的实现

4.队列的实现

5.deque容器

5.1 deque的存储结构

 5.2 deque的优缺点

6.优先队列

6.1仿函数的定义

6.2优先队列中使用仿函数

6.3优先队列的实现


1.认识栈和队列

栈是只在队尾进行插入和删除的线性表

队列是允许在一端进行插入操作而在另一端进行删除的线性表

都是线性表,那么有两种实现方式,即:顺序表,链表

队列
顺序表<vector>顺序栈顺序队列
链表<list>链栈链队列

因为可以有两种不同的底层存储方式,所以栈和队列被设计为容器适配器。

2.容器适配器

了解容器适配器之前,我们先来了解一下适配器:

适配器是一种设计模式,该模式可以让一种接口转换为用户所希望的另外一个接口

比如下图:用户希望得到一个交流电插头,就将标准插头和交流电适配器结合,就可以得到用户希望的交流电插头。

容器适配器是对已有的容器进行封装来实现其他容器。比如stack适配器对vector进行封装,提供接口,使其实现stack的功能。

容器适配器可以让开发者使用一种容器接口,但实际上使用的是另一种容器。

C++标准库提供了三种常见的容器适配器:栈(stack),队列(queue)和优先队列(priority——queue)

3.栈的实现

stack - C++ Referencehttps://legacy.cplusplus.com/reference/stack/stack/

代码实现:

template<class T, class container = deque<T>>
	class stack
	{
	public:
		void push(const T& x)
		{
			return Con.push_back(x);
		}

		void pop()
		{
			return Con.pop_back();
		}

		T& top()
		{
			return Con.back();
		}
		const T& top()const
		{
			return Con.back();
		}

		size_t size()const
		{
			return Con.size();
		}

		bool empty()const
		{
			return Con.empty();
		}

	private:
		container Con;
	};

4.队列的实现

queue - C++ Referencehttps://legacy.cplusplus.com/reference/queue/queue/

代码实现: 

template<class T, class container = deque<T>>
	class queue
	{
	public:
		void push(const T& x)
		{
			return Con.push_back(x);
		}

		void pop()
		{
			return Con.pop_front();
		}

		T& front()
		{
			return Con.front();
		}
		const T& front()const
		{
			return Con.front();
		}

		size_t size()const
		{
			return Con.size();
		}

		bool empty()const
		{
			return Con.empty();
		}

	private:
		container Con;
	};

5.deque容器

观察上述发现,我们给的容器默认参数都是deque,也侧面说明deque可以同时支持list和vector两种容器的操作

deque - C++ Referencehttps://legacy.cplusplus.com/reference/deque/deque/

deque的结构

deque是一个双开口的连续空间的数据结构。

双开口:可以在两端进行插入和删除操作。

5.1 deque的存储结构

 但deque并不是一个连续空间,而是由一个一个小的连续空间拼接而成的。

 中控数组:存放每一块连续空间的起始位置。当中控数组满的时候,扩容即可。

 operater[](size_t i)

{

        1.先看在不在第一个buff数组,如果在就找位置访问

        2.如果不在第一个数组

                在第几个buff=i/buffsize

                在第几个buff的第几个=i%buffsize

}

 5.2 deque的优缺点

相比vector:

极大的解决了头插和头删的问题

但[ ]不够极致,需要计算在哪个buff,在哪个buff 的第几个

相比list:

1.可以支持下标随机访问

2.cpu高速缓存效率不错

3.头尾插入和删除都不从,但是从中间删除很拉胯

5.3 deque的迭代器:

 

6.优先队列

优先级队列会对队内元素自动进行从大到小的排列。大的元素先出

优先级队列也是容器适配器,底层的数据结构是一个堆(默认是大堆),默认适配的容器是vector。

6.1仿函数的定义

仿函数是一种具有函数行为的类,在类内重载了运算符(),使对象可以像函数一样调用

实例代码

class Adder {
public:
    int operator()(int a, int b) {
        return a + b;
    }
};

int main() {
    Adder adder; // 创建一个仿函数对象
    int result = adder(3, 4); // 调用仿函数
    std::cout << "The result is: " << result << std::endl;

    return 0;
}
6.2优先队列中使用仿函数
class Less
	{
	public:
		bool operator()(const T& x,const T& y)
		{
			return x < y;
		}
	};

	template<class T>
	class Greater
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};
6.3优先队列的实现
template<class T,class container=vector<T>,class compare=Less<T>>
class priority_queue
{
private:
	container _con;
	compare Com;

	void AdjustUp(int child)
	{
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			if (Com(_con[child], _con[parent]))
			{
				swap(_con[child], _con[parent]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
			{
				break;
			
		}

	}

	void AdjustDown(int parent)
	{
		int child = parent * 2 + 1;
		size_t n = _con.size();

		while (child < n)
		{
			if (child + 1 < _con.size() && Com(_con[child], _con[child + 1]))
			{
				++child;
			}

			if (Com(_con[child], _con[parent]))
			{
				swap(_con[child], _con[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
			{
				break;
			}
		}

	}

public:
	priority_queue()
	{}

	//typedef container::iterator InputIterator;
	template<class InputIterator>
	priority_queue(InputIterator first,InputIterator last)
	{
		while (first != last)
		{
			_con.push_back(*first);
			++first;
		}
	}

	void push(const T& x)
	{
		_con.push_back(x);
		AdjustUp(_con.size()-1);
	}

	void pop()
	{
		size_t n = _con.size();
		swap(_con[0], _con[n - 1]);
		_con.pop_back();
		AdjustDown(0);
	}


	bool empty()
	{
		return _con.empty();
	}

	size_t size()const
	{
		return _con.size();
	}

	const T& top()
	{
		return _con[0];
	}
};

测试案例:

void test_priority_queue2()
{
	struct LessPDate
	{
		bool operator()(const Date* p1, const Date* p2)
		{
			return *p1 < *p2;
		}
	};
	
	//新构造一个仿函数LessPDate,Less和Greater比较的都是其存储地址,每一次的结果都会变
	mystl::priority_queue<Date*,vector<Date*>,LessPDate> pq;
	pq.push(new Date(2023, 7, 20));
	pq.push(new Date(2023, 6, 20));
	pq.push(new Date(2023, 8, 20));

	while (!pq.empty())
	{
		cout << *pq.top() << " ";
		pq.pop();
	}
	cout << endl;
}

输出结果:2023-6-20 2023-7-20 2023-8-20

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值