数据结构复习:栈和队列
栈
1.栈的定义:栈是一种操作受限的线性表,只允许在表的同一端进行插入和删除操作。
2.栈的特性:后进先出(Last in First out, LIFO)。
3.栈的实现:
①c语言版(数组简单实现),确保peek,pop,操作的合法性:
#include <stdio.h>
#define Maxn 10005
int Arr[Maxn], top = -1;
void push(int x)
{
Arr[++top] = x;
}
int empty()
{
return top == -1;
}
void pop()
{
top--;
}
int peek()
{
return Arr[top];
}
void clear()
{
top = -1;
}
int size()
{
return top + 1;
}
int full()
{
return top == Maxn - 1;
}
int main()
{
int n; //输入的个数;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
int tem;
scanf("%d", &tem);
push(tem);
}
while(size())
{
printf("*%d*", peek());
pop();
}
return 0;
}
(链表实现):
#include <cstdio> //c语言stdio.h
struct Node{
int data;
Node *nxt = NULL;
};
Node* top = nullptr;
void push(int x)
{
Node *p = new Node;
//Node *p = malloc(sizeof(Node));
p->data = x;
p->nxt = top;
top = p;
}
bool empty() //C语言没有bool类型,可以包含一个stdbool.h或者直接改为int类型
{
return top == NULL;
}
int size()
{
Node *r = top;
int cnt = 0;
while(r)
{
cnt++;
r = r->nxt;
}
return cnt;
}
int peek()
{
return top->data;
}
void pop()
{
Node *p = top;
top = top->nxt;
delete p;
//free(p);
}
void clear()
{
Node* p = top;
while(p)
{
top = p->nxt;
delete p;
p = top;
}
}
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
int tem;
scanf("%d", &tem);
push(tem);
printf("%d ", size());
}
printf("\n");
while(!empty())
{
printf("%d ", peek());
pop();
}
return 0;
}
②c++:STL中c++的stack是一个容器接口,c++中底层实现是deque,效率较低。
部分模板如下(取自c++程序设计语言第四部分):
template <typename T, typename C = deque<T>>
class stack{
public:
using value_type = typename C::value_type;
using reference = typename C::reference;
using const_reference = typename C::const_reference;
using size_type = typename C::size_type;
using container_type = C;
public:
explicit stack(const C&); //从容器拷贝;
explicit stack(C&& = C{}); //从容器移动;
//默认拷贝/移动构造函数/赋值操作
template<typename A>
explicit stack(const A& a); //默认容器,分配器为A;
template<typename A>
stack(const C&c, const A& a); //从C中获得容器,分配器为a;
template<typename A>
stack(C&&, const A&);
template<typename A>
stack(const stack&, const A& );
template<typename A>
stack(stack&&, const A&);
bool empty() const {return c.empty()};
size_type size() const{ return c.size()};
reference top{return c.back};
const_reference top() const {return c.back()};
void push(const value_type& x) {c.push_back(x)};
void push(value_type&& x) {c.push_back(std::move(x))};
void pop() {c.pop_back};
template <typename... Args>
void emplace(Args&&... args);
{
c.emplace_back(std::forward<Args>(args)...);
}
void swap(stack&s) noexcept(noexcept(swap(c,s.c)))
{
using std::swap;
swap(c,s.c);
}
protected:
C c;
};
4.单调栈:单调栈是一种特殊的栈,它保证了栈中元素大小单调递增或者单调递减。适用于取当前元素左(右)边第一个最大(小)元素。
核心代码:
stack <int> s;
while(!s.empty() && s.top() <= Data[i]) s.pop();
时间复杂度为O(1);
队列
1.队列的定义:队列是一种操作受限的线性表,所有元素的插入操作都在一段进行,而删除操作都在另一端进行。
2.队列的特性:先进先出(First in First out, FIFO);
3.队列的实现:
①C语言数组版
#include <cstdio> //stdio.h
#define Maxn 10005
int Arr[Maxn];
int front = 0, rear = 0, cnt = 0; // 队首下标,队尾下标;
void qpush(int x)
{
Arr[rear++] = x;
cnt++;
}
void qpop()
{
front++;
cnt--;
}
int qfront()
{
return Arr[front];
}
bool qempty() //int qempty()
{
return front == rear;
}
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
int tem;
scanf("%d", &tem);
qpush(tem);
}
while(!qempty())
{
printf("%d ", qfront());
qpop();
}
return 0;
}
链式实现:
#include <cstdio>
struct Node{
int data;
Node* next = NULL;
};
Node* front = NULL, *rear = NULL;
void qpush(int x)
{
Node* r = new Node;
//Node* r = malloc(sizeof(Node));
r->data = x;
if(!front) front = r;
if(rear) rear->next = r;
rear = r;
}
int qfront()
{
return front->data;
}
void qpop()
{
Node *r = front;
front = r->next;
delete r;
//free(r);
}
bool qempty() //int
{
return front == rear->next;
}
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
int tem;
scanf("%d", &tem);
qpush(tem);
}
while(!qempty())
{
printf("%d ",qfront());
qpop();
}
return 0;
}
②c++中STL部分实现:与栈类似。
4.单调队列:单调队列是队内元素保持单调递增或递减的特殊队列。适用于求连续一段数的最值。
核心实现:
//单调性维护
while(front < rear && num[que[rear - 1]] > num[i]) rear--;
que[rear++] = i;
//区间维护
while(front < rear && que[front] < i - m + 1) front++;