数据结构.第三章.栈和队列(纯纯复习又增加了耶)

目录

顺序栈

链栈

顺序栈和链栈的比较

队列

顺序队列

 循环队列

链队列

 循环队列与链队列的比较


  栈限定在表的一端进行插入和删除操作的线性表。

栈顶:插入和删除端 

栈底:另一端

空栈:不含任何元素的栈

特性:后进先出,先进后出

栈的功能:初始化、销毁、入栈、出栈、取栈顶元素、判空。

顺序栈

一维数组实现,下标为0作栈底,同时设置top变量指示栈顶元素的位置。

栈空:top = -1

栈满:top = StackSize-1

入栈:top++;出栈:top--

const int StackSize = 10;
template<typename T>
class SeqStack
{
	T data[StackSize];
	int top;
public:
	SeqStack()//初始化
	{
		top = -1;
	}
	~SeqStack() {}//销毁
	void Push(T x)//进栈
	{
		if (top == StackSize - 1)throw"上溢";
		data[++top] = x;
	}
	T Pop()//出栈
	{
		if (top == -1)throw"下溢";
		T x;
		x = data[top--];
		return x;//直接return data[top--]也ok
	}
	T GetTop()//取栈顶元素
	{
		return data[top];
	}
	int Empty()//判空
	{
		return(top == -1 ? 1 : 0);
	}
};

链栈

通常为单链表表示。  

  

template<typename T>
struct Node
{
	T data;
	Node<T>* next;
};
template<typename T>
class LinkStack
{
	Node<T>* top;//栈顶为链栈的头指针
public:
	LinkStack();//初始化
	~LinkStack();//释放存储空间
	void Push(T x);//进栈
	T Pop();//栈顶元素出栈
	T GetTop();//取栈顶元素
	int Empty();//判空
};

构造函数:top置空

析构函数:单链表释放直接代入

进栈://肥肠easy 自己画个图就能理解

template<typename T>
void LinkStack<T>::Push(T x)
{
	Node<T>* s = new Node<T>;
	s->data = x;
	s->next = top;
	top = s;
}

出栈

template<typename T>
T LinkStack<T>::Pop()
{
	T x;
	if (top == nullptr)throw"下溢";
	x = top->data;
	Node<T>* p = top;
	top = top->next;
	delete p;
	return x;
}

取栈顶:直接return top->data,但是元素不要出栈。

判空:看top是否为空

顺序栈和链栈的比较

顺序栈和链栈的基本操作的时间复杂度为O(1),空间性能是唯一可比的。

顺序栈:有存储元素个数限制和空间浪费问题。

链栈:除非内存没有可用空间时才会栈满,但每个元素都有指针域,从而产生了结构性开销。

元素变化个数较大时用链栈,反之用顺序栈。


队列

只允许在一端进行插入操作,在另一端进行删除操作的线性表 

队尾:允许插入的一端

队头:允许删除的一端

特性:先进先出

队列的功能:初始化、销毁、入队、出队、读取队头元素、判空

顺序队列

设置位置变量rear:

假设顺序队列的把队列的所有元素存储在数组的前n个单元,入队操作相当于追加,则时间复杂度为O(1);但是出队需要把每个元素向前移一个位置,时间复杂度为O(n)。

设置位置变量rear&front:

front 指向队头元素的前一个位置,rear 指向队尾元素的位置。 

出队:front ++;入队rear++

 循环队列

假溢出:因为设置了front后元素不移动,整个队列向数组的高端移动,产生了“单项移动性”。当元素被插入到数组中下标最大的位置后数组空间就用尽了,但是数组低端仍有空闲空间。

循环队列:解决假溢出 头尾相连的循环结构,

设存储队列的数组长度为 QueueSize, rear = (rear+1)%QueueSize

队空:front = rear

队满:rear = (front+1)%QueueSize

const int QueueSize = 100;
template<typename T>
class CirQueue
{
	int front, rear;
	T data[QueueSize];
public:
	CirQueue();//初始化
	~CirQueue() {};
	void EnQueue(T x);//进队
	T DeQueue();//出队
	T GetHead();//获取队头元素
	int Empty();//判空
};

初始化

template<typename T>
CirQueue<T>::CirQueue()
{
	front = rear = QueueSize - 1;//front和rear指向同一处,一般为数组的高端
}

入队

template<typename T>
void CirQueue<T>::EnQueue(T x)
{
	if ((rear + 1) % QueueSize == front)throw"上溢";
	rear = (rear + 1) % QueueSize;//队尾在循环的意义下+1
	data[rear] = x;
}

出队

template<typename T>
T CirQueue<T>::DeQueue()
{
	if (front == rear)throw"下溢";
	front = (front + 1) % QueueSize;
	return data[front];
}

判空:front =rear

取队头元素:data[(front+1)%QueueSize] 

链队列

队头指针始终指向链队列的头结点,队尾指针指向终端节点

template<typename T>
struct Node
{
	T data;
	Node<T>* next;
};
template<typename T>
class LinkQueue
{
private:
	Node<T>* front, * rear;
}

入队

1:rear->next =s;

2:rear = s;

template<typename T>
void LinkQueue<T>::EnQueue(T x)
{
	Node<T>* s = new Node<T>;
	s->data = x;
	rear->next = s;
	rear = s;
	s->next = nullptr;
}

出队

1:p=front->next;

2:front->next =p->next;

template<typename T>
T LinkQueue<T>::DeQueue()
{
	if (front == rear)throw"下溢";
	T x;
	Node<T>* p = new Node<T>;
	p = front->next;
	x = p->data;
	front->next = p->next;
	if (p->next == nullptr)rear = front;//出对前队列长度为1
	delete p;
	return x;
}

取队头: return front->next->data

判空: front==rear

 循环队列与链队列的比较

两者基本操作的时间复杂度均为O(1),可比的还是空间能动性。

(参考之前顺序栈和链栈的比较原理)


使用的书籍:《数据结构——从概念操C++实现(第三版)》王红梅 王慧 王新颖 编著

ps:美女的头发要肝没啦555

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值