关于栈和队列的相关操作

1、栈  分为顺序栈和链栈  对应数组和链表

top指向栈顶元素,设置空栈为-1;存在一个元素时top=0

栈的长度为StackSize

定义栈的结构体:

 1 #include "stdio.h"
 2
 3 /* 存储空间初始分配量 */
 4 #define MAXSIZE 20
 5
 6 /* SElemType类型根据实际情况而定,这里假设为int */
 7 typedef int SElemType;
 8
 9 /* 顺序栈结构 */
10 typedef struct
11 {
12     SElemType data[MAXSIZE];
13     int top; /* 用于栈顶指针 */
14 }SqStack;
15
16 int main()
17 {
18 }

进栈操作:push

1 int Push(SqStack * S, SElemType e){
2     if(S->top == MAXSIZE-1){
3         //栈满
4         return 0;
5     }
6     S->top++;
7     S->data[S->top] = e;
8     return 1;
9 }

初始化一个空栈:

//初始化栈
int InitStack(SqStack S){
    S->top = -1;
    return 1;
}

栈的遍历:

 1 /* 从栈底到栈顶依次对栈中每个元素显示 */
 2 Status StackTraverse(SqStack S)
 3 {
 4     int i;
 5     i=0;
 6     while(i<=S.top)
 7     {
 8         visit(S.data[i++]);
 9     }
10     printf("\n");
11     return OK;
12 }
13
14 Status visit(SElemType c)
15 {
16     printf("%d ",c);
17     return OK;
18 }

注:S->top代表着栈对应数组的下标0,1,2 。。。

出栈:

1 int Pop(SqStack* S, SElemType* e){
2     if(-1 == S->top){
3         return 0;
4     }
5     *e = S->data[S->top];
6     S->top--;
7     return 1;
8 }

获取栈顶元素:

1 /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
2 Status GetTop(SqStack S,SElemType *e)
3 {
4     if (S.top==-1)
5         return ERROR;
6     else
7         *e=S.data[S.top];
8     return OK;
9 }

判断栈是否为

1 /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
2 Status StackEmpty(SqStack S)
3 {
4     if (S.top==-1)
5         return TRUE;
6     else
7         return FALSE;
8 }

置空栈:

1 /* 把S置为空栈 */
2 Status ClearStack(SqStack *S)
3 {
4     S->top=-1;
5     return OK;
6 }

2、链栈

链栈对应不含头结点的单链表

top代表指向栈顶的指针,这里和链表中的next合并为一个,当top=null时,链栈为空

定义链栈的结构体:

下面是单链表的结构体:

1 typedef struct Node
2 {
3     ElemType data;
4     struct Node *next;
5 }Node;
6 typedef struct Node *LinkList; /* 定义LinkList */

相似的链栈的结构体为:

1 /* 链栈结构 */
2 typedef struct StackNode
3 {
4     SElemType data;
5     struct StackNode *next;
6 } StackNode,*LinkStackPtr;

这只是链栈一个节点的定义,还需要添加链栈的栈顶指针:

 1 typedef int Status;
 2 /* SElemType类型根据实际情况而定,这里假设为int */
 3 typedef int SElemType;
 4
 5 /* 链栈结构 */
 6 typedef struct StackNode
 7 {
 8     SElemType data;
 9     struct StackNode *next;
10 } StackNode,*LinkStackPtr;
11
12 typedef struct
13 {
14     LinkStackPtr top;
15     int count;
16 } LinkStack;

其中count是用来计算栈中元素的个数的,也可以根据需要添加属性等

入栈,其实就是添加新的节点,下面这张图描述的很清楚:

实际上就两步:1、将新的节点next指向原栈顶元素  2、将top指针指向新的节点

1 int Push(LinkStack* L, SElemType e){
2     //首先分配节点
3     LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
4     p->data = e;
5     p->next = S->top;
6     S->top = p;
7     S->count++;
8     return 1;
9 }

初始化空栈:条件count=0,且top为null

 1 /*  构造一个空栈S */
 2 Status InitStack(LinkStack *S)
 3 {
 4     S->top = (LinkStackPtr)malloc(sizeof(StackNode));
 5     if(!S->top)
 6         return ERROR;//分配失败
 7     S->top=NULL;
 8     S->count=0;
 9     return OK;
10 }

遍历的过程和链表完全类似,这里不再赘述:

 1 Status StackTraverse(LinkStack S)
 2 {
 3     LinkStackPtr p;
 4     p=S.top;
 5     while(p)
 6     {
 7         visit(p->data);
 8         p=p->next;
 9     }
10     printf("\n");
11     return OK;
12 }
13
14 Status visit(SElemType c)
15 {
16     printf("%d ",c);
17     return OK;
18 }

出栈操作:这里主要注意一点就是删除的节点要释放掉 核心代码就是S->top = S->top->next;

 1 /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
 2 Status Pop(LinkStack *S,SElemType *e)
 3 {
 4     LinkStackPtr p;
 5     if(StackEmpty(*S))
 6         return ERROR;
 7     *e=S->top->data;
 8     p=S->top;                    /* 将栈顶结点赋值给p,见图中① */
 9     S->top=S->top->next;    /* 使得栈顶指针下移一位,指向后一结点,见图中② */
10     free(p);                    /* 释放结点p */
11     S->count--;
12     return OK;
13 }

注:这里的Status是预定义的,这里简化表示int

置空链栈会比顺序栈稍微复杂一些:置空顺序栈只需一步S->top = -1即可,而对于链栈置空实质上就是删除整个链表所有的节点,这里关键的问题就是移动待删除节点指针到下一个位置后,没法直接free掉,这样说起来不好理解,直接看代码:

 1 /* 把S置为空栈 */
 2 Status ClearStack(LinkStack *S)
 3 {
 4     LinkStackPtr p,q;
 5     p=S->top;
 6     while(p)
 7     {
 8         q=p;
 9         p=p->next;
10         free(q);
11     }
12     S->count=0;
13     return OK;
14 }

其实就是先将待删除节点付给一个临时指针,然后当前指针移动到下一个位置后,就可以将这个临时指针给free掉

那这里来分析一下顺序栈和链栈的区别:两者的时间复杂度都为O(1)
顺序栈定位元素更加方便,需提前分配内存区域;链栈在内存充足的情况下大小是无限的,存取定位没有顺序栈快,每个节点还有指针域,某种程度上增加了空间开销

所以根据不同情况选择

时间: 2024-10-29 05:50:48

关于栈和队列的相关操作的相关文章

关于栈和队列的相关问题

#include<iostream> using namespace std; #include<stack> #include<queue> #include<assert.h> //template<class T> //两个栈实现一个队列 //class StackToqueue //{ //public: // StackToqueue() // {} // void Push(const T& x) // {//始终保持让栈1进

栈与队列的相关题目

栈的实现(数组) 1 template<typename T> class ArrayStack { 2 public: 3 ArrayStack(int c = 100): capacity(c), top(-1) { 4 data = new T[capacity](); 5 } 6 ArrayStack(const ArrayStack &rhs):capacity(rhs.capacity), top(rhs.top) { 7 data = new T[capacity]();

数据结构与算法系列研究二——栈和队列

栈和队列的相关问题分析 一.栈和队列定义 栈和队列是两种重要的数据结构.从结构特性角度看,栈和队列也是线性表,其特殊性在于它们的基本操作是线性表的子集,是操作受限的线性表,可称为限定性的数据结构:从数据类型角度看,其操作规则与线性表大不相同,是完全不同于线性表的抽象数据类型.                    图1 栈的结构                                                 图2 队列的结构   1.1.栈是限定在表的一端进行插入和删除操作的线性

Coursera Algorithms week2 栈和队列 Interview Questions: Queue with two stacks

题目原文: Implement a queue with two stacks so that each queue operations takes a constant amortized number of stack operations. 题目要求用栈实现队列的所有操作. 1 import java.util.Iterator; 2 import edu.princeton.cs.algs4.Stack; 3 public class QueueWith2Stacks<Item>{

小猪的数据结构辅助教程——3.1 栈与队列中的顺序栈

小猪的数据结构辅助教程--3.1 栈与队列中的顺序栈 标签(空格分隔): 数据结构 本节学习路线图与学习要点 学习要点 1.栈与队列的介绍,栈顶,栈底,入栈,出栈的概念 2.熟悉顺序栈的特点以及存储结构 3.掌握顺序栈的基本操作的实现逻辑 4.掌握顺序栈的经典例子:进制变换的实现逻辑 1.栈与队列的概念: 嗯,本节要进行讲解的就是栈 + 顺序结构 = 顺序栈! 可能大家对栈的概念还是很模糊,我们找个常见的东西来拟物化~ 不知道大家喜欢吃零食不--"桶装薯片"就可以用来演示栈! 生产的时

【leetcode 简单】 第六十六题 用栈实现队列

使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返回队列首部的元素. empty() -- 返回队列是否为空. 示例: MyQueue queue = new MyQueue(); queue.push(1); queue.push(2); queue.peek(); // 返回 1 queue.pop(); // 返回 1 queue.empty(); // 返回 false 说明: 你只能使用标准的栈操

leecode刷题(26)-- 用栈实现队列

leecode刷题(26)-- 用栈实现队列 用栈实现队列 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返回队列首部的元素. empty() -- 返回队列是否为空. 示例: MyQueue queue = new MyQueue(); queue.push(1); queue.push(2); queue.peek(); // 返回 1 queue.pop(); // 返回 1 queue.empty

LeetCode 232:用栈实现队列 Implement Queue using Stacks

题目: 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返回队列首部的元素. empty() -- 返回队列是否为空. Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of queue. pop() -- Removes the element from in

栈的实现 与 用两个栈实现队列

栈的实现 /** * 栈的实现:数组 */ class MyStack1<T>{ private T[] data; private int maxLength; private int top; public MyStack1(int maxLength) { this.maxLength = maxLength; this.data= (T[])new Object[maxLength]; top=-1; } public boolean isFull(){ if(top==maxLeng