一、概念
1.栈
栈是一种只能在其一端存取数据的线性表,这种操作方法决定了它的一个特点:先进后出,后进先出,你可以把它想象为生活中任意一个只有一个口的容器,你只有把后边放进去的东西拿出来之后才能去取之前放进去的东西,栈存取数据的一端被称为栈顶.
2.队列
队列是在其一端插入数据、在另一端取出数据的线性表,它的特点是先进先出,就好似现实中的排队一样,先到的先办完事情出队,队列插入数据的一端被称为尾,删除数据的一端被称为队首.
二、栈和队列的操作方式
//栈
1、顺序栈
顺序栈就相当于用数组保存数据,top记录栈顶元素或者其上一个空间的下标,入栈和出栈代码如下。
struct stack
{
int * data;
int top;
}stack;
stack.data[stack.top] = value;
stack.top++;
stack.top--;
stack.data[stack.top] = 0;
这里入栈和出栈在某种意义上可以说是逆序,其原因可以自己画图理解。
2、链栈
链栈在节点组织上有如下两种方式:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b88e51bae4cdf9b729e2e3616fe6a65b.png)
这两种方式我们选第一种,因为第二种方式得维护一个栈低指针,并且在每一次出栈时都必须从栈底遍历一遍整个栈以便找到指向栈顶节点的节点, 才能删除栈顶元素。用第一种组织结构出栈入栈方法如下:
typedef struct StackNode
{
int data;
struct StackNode * link;
}StackNode;
typedef struct Stack
{
StackNode * top;
}Stack;
StackNode *p = (StackNode *)malloc(sizeof(StackNode));
p->data = value;
p->link = Stack.top;
Stack.top = p;
StackNode *p = Stack.top;
Stack.top = Stack.top->link;
free(p);
//队列
1、顺序队列
用数组存储的队列有一个缺点,在出队的时候,把第一个元素删除,那就得把后边所有元素向前挪一个位置,浪费时间,解决的办法是出队不挪元素,我们让队首下标加一就行,但是这又有一个致命的缺点,随着入队出队的次数越来越多,数组空间越来越大,但是队首之前却又大片空间被闲置着,造成了空间上的浪费。那么最终的解决办法就是循环队列,在逻辑意义上将数组的尾部和首部连接起来形成一个环,这样在入队时虽然尾部满了,但是如果队首有空间,依然会成功插入,要想实现这一点,我们得依赖取模运算符%,代码如下:
struct Queue
{
int * data;
int head;
int tail;
int capacity;
}Queue;
Queue.head == Queue.tail;
(Queue.tail + 1) % (Queue.capacity + 1) == Queue.head;
Queue.tail = value;
Queue.tail = (Queue.tail + 1) % (Queue.capacity + 1)
Queue.head = 0;
Queue.head = (Queue.head + 1) % (Queue.capacity + 1)
对capacity+1取模得到的是0~capacity,刚好满足要求。
2、链队
这里也就没什么好说的了,直接给出代码:
typedef struct QueueNode
{
int data;
struct QueueNode * link;
}QueueNode;
typedef struct Queue
{
QueueNode * head;
QueueNode * tail;
}Queue;
QueueNode *p = (QueueNode *)malloc(sizeof(Queue));
p->data = value;
p->link = NULL;
Queue.tail->link = p;
Queue.tail = p;
QueueNode *p = Queue.head;
Queue.head = Queue.head->link;
free(p);
三、栈实现队列,队列实现栈
我认为这可以是用于学习,开发思维,但好像没什么用,用栈我建一个栈就行了,为什么非要搞两个队列来弄,浪费时间又浪费空间,没道理。所以我这里只总结一下原理吧。
用栈实现队列就是建两个栈,一个作为存数据的栈,一个作为辅助栈,入队时直接往数据栈压栈就行,主要是出队,因为栈不允许从栈低取数据,所以需要先把上边n-1个数据出栈,出到哪呢,总不能扔了吧,这时候就要用到辅助栈了,把数据从数据栈中取出,入到辅助栈中,取出想要的数据,也就是出队,然后再来个反过程,将数据再倒回去,因为栈操作方式是一样的,所以数据倒回去之后顺序没变。
用队列实现栈也是这么个原理,大家可以自己揣摩揣摩!!!