1、堆栈 javascript
堆栈是编程中有用的数据结构。就像一堆盘子彼此叠放。java

想想用这样一堆盘子能够作的事情python
在上面放一个新盘子ios
卸下顶部盘子web
持续来回作实验就知道了堆栈的意义
算法
若是要将板放在底部,则必须先卸下顶部的全部板。这种安排称为“后进先出”-放置的最后一个元素是第一个外出元素。编程
LIFO堆栈原理
用编程的术语来讲,将一个元素放在堆栈的顶部称为“推”,而将一个元素删除则称为“弹出”。数组

在上图中,尽管元顶部3最后才保留,但它首先被移除-所以它遵循后进先出(LIFO)原则。浏览器
堆栈的基本操做
堆栈是一个对象,或更具体地说,是一个容许执行如下操做的抽象数据结构(ADT):微信
Push
:将元素添加到堆栈顶部Pop
:从堆栈顶部删除元素IsEmpty
:检查堆栈是否为空IsFull
:检查堆栈是否已满Peek
:获取顶部元素的值而不删除它
堆栈数据结构的工做
操做以下:
称为TOP用于跟踪堆栈中的顶部元素。
初始化堆栈时,将其值设置为-1,以即可以经过比较来检查堆栈是否为空
TOP == -1
。推送元素时,增长了TOP并将新元素放置在所指向的位置TOP。
弹出元素时,返回由指向的元素TOP并下降其值。
推入以前,检查堆栈是否已满
弹出以前,检查堆栈是否已为空

Python,C和C ++中的堆栈实现
最多见的堆栈实现是使用数组,可是也可使用列表来实现。
C:
// Stack implementation in C
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
/*堆栈最大存储元素基数*/
#define MAX 10
int count = 0;
// Creating a stack
struct stack
{
int items[MAX];//堆栈元素数组
int top;
};
typedef struct stack st;
void createEmptyStack(st *s)
{
s->top = -1;
}
// Check if the stack is full
int isfull(st *s)
{
if (s->top == MAX - 1)
return 1;
else
return 0;
}
// Check if the stack is empty
int isempty(st *s)
{
if (s->top == -1)
return 1;
else
return 0;
}
// Add elements into stack
void push(st *s, int newitem)
{
if (isfull(s))
{
printf("STACK FULL");
}
else
{
s->top++;//相似索引递增
s->items[s->top] = newitem;
}
count++;//计算次数=个数=添加几个元素
}
// Remove element from stack
void pop(st *s)
{
if (isempty(s))
{
printf("\n STACK EMPTY \n");
}
else
{
printf("Item popped= %d", s->items[s->top]);//--的形式从数组里移除元素
s->top--;//逐一减去
}
count--;
printf("\n");
}
// Print elements of stack
void printStack(st *s)
{
printf("Stack: ");
for (int i = 0; i < count; i++)
{
printf("%d ", s->items[i]);
}
printf("\n");
}
// 执行 code
int main()
{
int ch,i;
st *s = (st *)malloc(sizeof(st));
/*分配一个sizeof(st)大小的空间,而且把该空间的地址赋给st指针类型的p*/
createEmptyStack(s);
#if 0
push(s, 1); //推元素1
push(s, 2); //推元素2
push(s, 3); //推元素3
push(s, 4); //推元素4
#endif
/*也能够写成循环的形式*/
int j;
for (i = 1; i < 5; i++)
{
j = i * (i + 1);
push(s, j);
// printf("%d\n",i);
}
printStack(s);
printf("cnt = %d\n", count);
/*堆栈第一次移除*/
pop(s);
printf("\n堆栈第一次移除After popping out\n");
printStack(s);
printf("cnt0 = %d\n", count);
/*堆栈第一次移除*/
pop(s);
printf("\n堆栈第二次移除After popping out\n");
printStack(s);
printf("cnt1 = %d\n", count);
system("pause");
return 0;
}
执行结果:
C++:
// Stack implementation in C++
#include <stdlib.h>
#include <iostream>
using namespace std;
#define MAX 10
int size_t = 0;
// Creating a stack
struct stack
{
int items[MAX];
int top;
};
typedef struct stack st;
void createEmptyStack(st *s)
{
s->top = -1;
}
// Check if the stack is full
int isfull(st *s)
{
if (s->top == MAX - 1)
return 1;
else
return 0;
}
// Check if the stack is empty
int isempty(st *s)
{
if (s->top == -1)
return 1;
else
return 0;
}
// Add elements into stack
void push(st *s, int newitem)
{
if (isfull(s))
{
printf("STACK FULL");
}
else
{
s->top++;
s->items[s->top] = newitem;
}
size_t++;
}
// Remove element from stack
void pop(st *s)
{
if (isempty(s))
{
printf("\n STACK EMPTY \n");
}
else
{
printf("Item popped= %d", s->items[s->top]);
s->top--;
}
size_t--;
cout << endl;
}
// Print elements of stack
void printStack(st *s)
{
printf("Stack: ");
for (int i = 0; i < size_t; i++)
{
cout << s->items[i] << " ";
}
cout << endl;
}
// Driver code
int main()
{
int ch;
st *s = (st *)malloc(sizeof(st));
createEmptyStack(s);
push(s, 1);
push(s, 2);
push(s, 3);
push(s, 4);
printStack(s);
pop(s);
cout << "\nAfter popping out\n";
printStack(s);
cin.get();
return 0;
}
PYTHON:
# Stack implementation in python
# Creating a stack
def create_stack():
stack = [] #保存
return stack
# Creating an empty stack
def check_empty(stack):
return len(stack) == 0
# Adding items into the stack
def push(stack, item):
stack.append(item)
# 追加打印出结果 +
print("pushed item: " + item)
# Removing an element from the stack
def pop(stack):
if (check_empty(stack)):
return "stack is empty"
return stack.pop()
stack = create_stack()
# push(stack, str(1))
# push(stack, str(2))
# push(stack, str(3))
# push(stack, str(4))
for item in range(1,10):
push(stack, str(item))
pass
print("第 1 次移除popped item: " + pop(stack))
print("移除后剩余的元素stack after popping an element: " + str(stack))
print("第 2 次移除popped item: " + pop(stack))
print("移除后剩余的元素stack after popping an element: " + str(stack))
# 能够按照循环次数来移动
for item in range(5):
print("第",item+3, "次移除popped item: " + pop(stack))
print("移除后剩余的元素stack after popping an element: " + str(stack))
pass
执行结果:
堆栈时间复杂度
对于基于数组的堆栈实现,推入和弹出操做须要花费必定的时间,即O(1)
由于在两种状况下都只有指针移动。
堆栈数据结构的应用
尽管堆栈是一个易于实现的简单数据结构,但它很是强大。堆栈最多见的用途是:
反转单词-将全部字母叠放并弹出。因为堆栈的LIFO顺序,您将得到相反顺序的字母。
在编译器中-编译器使用堆栈来计算表达式的值,例如
2 + 4 / 5 * (7 - 9)
将表达式转换为前缀或后缀形式。在浏览器中-浏览器中的记录“后退”按钮会将您之前访问过的全部URL保存在堆栈中。每次您访问新页面时,它都会被添加到堆栈顶部。当您按下“后退”按钮时,当前URL从堆栈中删除,并访问前一个URL。
2、队列
队列是编程中有用的数据结构。它相似于电影院大厅外面的售票队列,在该队列中,第一个进入队列的人是第一个得到票的人。
队列遵循先进先出(FIFO)规则-先进入的项目也是先进入的项目。

在上图中,因为1在2以前保留在队列中,所以它也是第一个从队列中删除的队列。它遵循FIFO规则。
用编程术语来讲,将元素放入队列称为“入队”,而将元素从队列中删除则称为“出队”。
队列的基本操做
队列是一个对象,或更具体地说,是一个容许执行如下操做的抽象数据结构(ADT):
Enqueue:将元素添加到队列的末尾
Dequeue:从队列的前面删除一个元素
IsEmpty:检查队列是否为空
IsFull:检查队列是否已满
Peek:获取队列最前面的值而不删除它
队列工做
队列操做以下:
两个指针 FRONT 和 REAR
FRONT 跟踪队列的第一个元素
REAR 跟踪队列的最后一个元素
最初,设定值为 FRONT 和 REAR 至-1
入队操做
检查队列是否已满
对于第一个元素,设置为 FRONT至0
增长 REAR 索引1
在由指向的位置添加新元素 REAR
出队操做
检查队列是否为空
返回所指向的值 FRONT
增长 FRONT 索引1
对于最后一个元素,重置的值FRONT 和 REAR 至-1

Python,C和C ++中的队列实现
C:
// Queue implementation in C
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5
void enQueue(int value);
/*下面声明的仍是没有变量,是由于用全局变量代替了*/
void deQueue();
void display();
//定义数组全局变量
int items[SIZE], front = -1, rear = -1;
void enQueue(int value)
{
//若是队列后面的已经满了,此时size就不能继续入队列
if (rear == SIZE - 1)
printf("\nQueue is Full!!");
else
{
if (front == -1)
front = 0;
rear++;//则继续向前递增
items[rear] = value;//继续插入入栈元素
printf("\nInserted -> %d", value);
}
}
void deQueue()
{
//出列
if (front == -1)
printf("\nQueue is Empty!!");
else
{
printf("\nDeleted : %d", items[front]);
front++;
if (front > rear)
front = rear = -1;
}
}
// Function to print the queue
void display()
{
if (rear == -1)
printf("\nQueue is Empty!!!");
else
{
int i;
printf("\nQueue elements are:\n");
for (i = front; i <= rear; i++)
printf("%d ", items[i]);
}
printf("\n");
}
int main()
{
//deQueue is not possible on empty queue
deQueue();
//enQueue 5 elements
enQueue(1);
enQueue(2);
enQueue(3);
enQueue(4);
enQueue(5);
//6th element can't be added to queue because queue is full
enQueue(6);//超过了size[5]的个数范围
display();//队列索引对应的元素
//deQueue removes element entered first i.e. 1
deQueue();
//Now we have just 4 elements
display();//展现移除后的对立
/*再出一次队列*/
deQueue();
display(); //展现移除后的对立
system("pause");
return 0;
}
执行结果:
C++
// Queue implementation in C++
#include <iostream>
#define SIZE 5
using namespace std;
class Queue
{
private:
int items[SIZE], front, rear;
public:
Queue()
{
front = -1;
rear = -1;
}
bool isFull()
{
if (front == 0 && rear == SIZE - 1)
{
return true;
}
return false;
}
bool isEmpty()
{
if (front == -1)
return true;
else
return false;
}
void enQueue(int element)
{
if (isFull())
{
cout << "Queue is full";
}
else
{
if (front == -1)
front = 0;
rear++;
items[rear] = element;
cout << endl
<< "Inserted " << element << endl;
}
}
int deQueue()
{
int element;
if (isEmpty())
{
cout << "Queue is empty" << endl;
return (-1);
}
else
{
element = items[front];
if (front >= rear)
{
front = -1;
rear = -1;
} /* Q has only one element, so we reset the queue after deleting it. */
else
{
front++;
}
cout << endl
<< "Deleted -> " << element << endl;
return (element);
}
}
void display()
{
/* Function to display elements of Queue */
int i;
if (isEmpty())
{
cout << endl
<< "Empty Queue" << endl;
}
else
{
cout << endl
<< "Front index-> " << front;
cout << endl
<< "Items -> ";
for (i = front; i <= rear; i++)
cout << items[i] << " ";
cout << endl
<< "Rear index-> " << rear << endl;
}
}
};
int main()
{
Queue q;
//deQueue is not possible on empty queue
q.deQueue();
//enQueue 5 elements
q.enQueue(1);
q.enQueue(2);
q.enQueue(3);
q.enQueue(4);
q.enQueue(5);
//6th element can't be added to queue because queue is full
q.enQueue(6);
q.display();
//deQueue removes element entered first i.e. 1
q.deQueue();
//Now we have just 4 elements
q.display();
//再移动一次
q.deQueue();
q.display();
cin.get();
return 0;
}
执行结果:
python:
# Circular Queue implementation in Python
class MyCircularQueue():
def __init__(self, k):
self.k = k
self.queue = [None] * k
self.head = self.tail = -1
# Insert an element into the circular queue
def enqueue(self, data):
if ((self.tail + 1) % self.k == self.head):
print("The circular queue is full\n")
elif (self.head == -1):
self.head = 0
self.tail = 0
self.queue[self.tail] = data
else:
self.tail = (self.tail + 1) % self.k
self.queue[self.tail] = data
# Delete an element from the circular queue
def dequeue(self):
if (self.head == -1):
print("The circular queue is empty\n")
elif (self.head == self.tail):
temp = self.queue[self.head]
self.head = -1
self.tail = -1
return temp
else:
temp = self.queue[self.head]
self.head = (self.head + 1) % self.k
return temp
def printCQueue(self):
if(self.head == -1):
print("No element in the circular queue")
elif (self.tail >= self.head):
for i in range(self.head, self.tail + 1):
print(self.queue[i], end=" ")
print()
else:
for i in range(self.head, self.k):
print(self.queue[i], end=" ")
for i in range(0, self.tail + 1):
print(self.queue[i], end=" ")
print()
# Your MyCircularQueue object will be instantiated and called as such:
obj = MyCircularQueue(5)
obj.enqueue(1)
obj.enqueue(2)
obj.enqueue(3)
obj.enqueue(4)
obj.enqueue(5)
print("Initial queue")
obj.printCQueue()
obj.dequeue()
print("After removing an element from the queue")
obj.printCQueue()
执行结果:
如您在下图中所看到的,在进行一些入队和出队后,队列的大小已减少。

只有当全部元素都已出队后,才能在重置队列后使用索引0和1。
后 REAR到达最后一个索引,若是咱们能够将多余的元素存储在空白处(0和1),则能够利用这些空白处。这是经过一个称为循环队列的修改队列来实现的 。
复杂度分析
使用数组的队列中入队和出队操做的复杂度为O(1)
。
队列数据结构的应用
CPU调度,磁盘调度
在两个进程之间异步传输数据时。队列用于同步。例如:IO缓冲区,管道,文件IO等
实时系统中的中断处理。
呼叫中心电话系统使用队列来令人们按顺序呼叫
参考文献
https://blog.csdn.net/weixin_41194129/article/details/109281031https://blog.csdn.net/weixin_41194129https://www.zhihu.com/people/zhou-kang-9-28
本文分享自微信公众号 - AI科技与算法编程(kangsinx)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。