数据结构——队列(queue)

一、顺序队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出线性表。

队列整体来说与栈类似,不过栈的特性是先进后出,二队列的特性是先进先出。

C语言实现:

1、队列的存储结构以及一些需要实现的方法

typedef char  ElemType;

#define SIZE 10
#define TRUE 1
#define FALSE 0


typedef struct queue
{
	ElemType *data;
	int head;
	int tail;

}queue, *pQueue;

void InitQueue(pQueue que);      //队列的初始化

int PushQue(pQueue que, ElemType val);    //入队列

int PopQue(pQueue que, ElemType *res);    //出队列

void DestroyQue(pQueue que);       //销毁队列

2、队列的判空判满以及初始化

static int IsFull(pQueue que)    //判满
{
	assert(que != NULL);

	if ((que->tail + 1) % SIZE == que->head)
	{
		return TRUE;
	}

	return FALSE;
}
    
static int IsEmpty(pQueue que)        //判空
{
	assert(que != NULL);

	if (que->head == que->tail)
	{
		return TRUE;
	}

	return FALSE;
}


void InitQueue(pQueue que)         //初始化
{
	assert(que != NULL);

	que->data = (ElemType*)malloc(sizeof(ElemType)* SIZE);
	assert(que->data != NULL);

	que->head = que->tail = 0;
}

3、入队列(push)

int PushQue(pQueue que, ElemType val)
{
	assert(que != NULL);

	if (IsFull(que))
	{
		return FALSE;
	}

	que->data[que->tail++] = val;
	que->tail %= SIZE;

	return TRUE;
}

4、出队列(pop)

int PopQue(pQueue que, ElemType *res)
{
	assert(que != NULL && que->data != NULL);

	if (IsEmpty(que))
	{
		return FALSE;
	}

	*res = que->data[que->head++];
	que->head %= SIZE;

	return TRUE;
}

5、销毁队列

void DestroyQue(pQueue que)
{
	assert(que != NULL);

	free(que->data);
	que->data = NULL;
	que->head = que->tail = 0;
}

这里我实现的是一个循环的顺序队列,当向队列中插入数据时,如果队列已到达队尾,则去判断队列头还有没有可以存储数据的位置,如果有则放在队列头。

C++实现:

typedef int  ElemType;
#define SIZE 10

class Queue
{
private:
	ElemType *_data;
	int _head;
	int _tail;
	bool IsFull();    //判满
	bool IsEmpty();    //判空
public:
	Queue();
	Queue(const Queue &src);    //拷贝构造函数
	Queue& operator= (const Queue& src);    //等号运算符的重载
	~Queue();
	bool Push(ElemType val);    //入队列
	bool Pop();    //出队列
	ElemType GetQue();    //去队列头的元素
	void show();    //打印整个队列
};
bool Queue::IsFull()
{
	assert(this != NULL);

	if ((_tail + 1) % SIZE == _head)
	{
		return true;
	}

	return false;
}
bool Queue::IsEmpty()
{
	assert(this != NULL);

	if (_head == _tail)
	{
		return true;
	}

	return false;
}
Queue::Queue()
{
	assert(this != NULL);

	_data = new ElemType[SIZE];
	assert(_data != NULL);
	_head = 0;
	_tail = 0;
}
Queue::Queue(const Queue &src)
{
	_data = new ElemType[sizeof(src._data)];
	for (int i = src._head; i < src._tail; ++i)
	{
		_data[src._head] = src._data[i];
	}
	_head = src._head;
	_tail = src._tail;
}
Queue& Queue::operator= (const Queue& src)
{
	if (this == &src)
	{
		return *this;
	}
	if (_data != NULL)
	{
		delete[]_data;
	}
	_data = new ElemType[sizeof(src._data)];
	for (int i = src._head; i < src._tail; ++i)
	{
		_data[src._head] = src._data[i];
	}
	_head = src._head;
	_tail = src._tail;

	return *this;
}
Queue::~Queue()
{
	if (NULL != _data)
	{
		delete[]_data;
		_data = NULL;
		_head = 0;
		_tail = 0;
	}
}
bool Queue::Push(ElemType val)
{
	assert(this != NULL);

	if (IsFull())
	{
		return false;
	}

	_data[_tail++] = val;
	_tail %= SIZE;

	return true;
}
bool Queue::Pop()
{
	assert(this != NULL && _data != NULL);

	if (IsEmpty())
	{
		return false;
	}

	_head++;
	_head %= SIZE;

	return true;
}
ElemType Queue::GetQue()
{
	assert(this != NULL);

	if (IsEmpty())
	{
		return 0;
	}

	return _data[_head];
}

void Queue::show()
{
	assert(this != NULL);

	for (int i = _head; i < _tail; i++)
	{
		cout << _data[i] << " ";
	}
	cout << endl;
}

二、链式队列

在队列的形成过程中,可以利用线性链表的原理,来生成一个队列。

利用链表的队列,要动态创建和删除节点,效率较低,但是可以动态增长。

队列采用的FIFO(first in first out),新元素(等待进入队列的元素)总是被插入到链表的尾部,而读取的时候总是从链表的头部开始读取。每次读取一个元素,释放一个元素。所谓的动态创建,动态释放。因而也不存在溢出等问题。由于链表由结构体间接而成,遍历也方便。

链式队列的实现:

template<typename T>
class Mqueue
	Mqueue()
{
public:
	{
		_head = NULL;
		_tail = NULL;
	}
	~Mqueue()
	{
		if (_head == NULL)
		{
			return;
		}

		while (_head != _tail)
		{
			pop();
		}
		delete _head;
		_head = _tail = NULL;
	}
	void push(T val)
	{
		Node *p = new Node;
		p->_val = val;
		p->_next = NULL;
		if (_head == NULL && _tail == NULL)
		{
			_head = p;
			_tail = p;
		}
		else
		{
			_tail->_next = p;
			_tail = p;
		}
	}
	int pop()
	{
		if (_head == NULL)
		{
			return -1;
		}
		Node *p = _head;
		_head = p->_next;
		p->_next = NULL;
		delete p;

	}
	T top()
	{
		return _tail->_val;
	}

	void show()
	{
		Node *p = _head;
		while (p != NULL)
		{
			cout << p->_val << "   ";
			p = p->_next;
		}
		cout << endl;
	}
private:
	class Node
	{
	private:
		T _val;
		Node *_next;

		friend class Mqueue;

	public:
		Node()
		{
			_next = NULL;
		}
	};

	Node *_head;
	Node *_tail;


};

猜你喜欢

转载自blog.csdn.net/wry_sunny_/article/details/88599451
今日推荐