数据结构之数组对栈的实现

简介: 数据结构之数组对栈的实现

1.什么是栈

栈是一种特殊的线性表,其中只允许固定的一端进行插入与删除,进行输出插入删除的那一端我们称为栈顶,与之相反的一端称为栈底。在栈中,元素遵循先进后出的原则即LIFO(last in first out)。

栈因为是一种操作受到限制的线性表:栈的特点是先进后出,类似于堆盘子,先放到地上的盘子最后被取走。栈的操作有两种:入栈和出栈。入栈就是把元素放到栈顶,出栈就是把栈顶元素取出来。我们也可以想象成弹夹,先装的子弹最后射出,后装的先射出。

0b5253ce42ce469190cc6d0cf6c41fff.png

2.栈的基本操作

对于栈,我们对他的操作只有入栈与出栈,就栈里的元素,增加与删除,需要注意的是因为规定的特殊结构

压栈,也称入栈,进栈,(增加元素)


d817baf6972946b7a129f8525d1fe789.png


出栈(删除元素)


47daad3450b045c48caf35cfbc83dad9.png

因为这种特殊的结构,我们会发现在操作时栈底的元素永远也不可能在他的前一个出栈,无论何时出栈还是入栈。

82f3f0737798483dba7d3c73dc39efbd.png


3.栈的实现

栈的实现也是多种多样:

1.数组实现:数组实现优点较为明显,我们可以下标访问每个栈中的元素,且结构简单,空间利用率高,唯一的缺点是当容量不足时我们需要扩容。

2..单链表实现:单链表也可以实现栈这种结构,但需要注意我们在出栈与入栈的时候,是需要知道为节点的前一个元素,而单链表是无法直接访问的,需要遍历时间复杂度为O(n),于是我们在实现时,是利用头节点作为栈顶的,入栈即就是头插的方式可以实现栈的结构,对于入栈与出栈时间复杂度为O(1),不过单链表在访问栈中的元素时时间复杂度还是O(n).

3.双链表实现:最不建议的一种实现方式,因为对于双链表不仅增加了节点里的指针,结构更复杂,空间利用也不高,且也就是双链表的头插方式实现的,相对于前两种实现,没这个必要。

所以今天我们就用优点较为明显的数组来实现栈,我们也会发现栈的实现其实是非常简单的。

1.结构体与函数接口

我们在定义栈的结构体时,发现还是跟顺序表的定义一样,不过表示实际元素大小我们这里用top表示,即我们称为栈顶也是大小,同时给出总容量。

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
#define DATAtype int 
typedef struct Stack
{
  DATAtype* a;//实现栈的数组
  int top;//记录栈顶
  int capacity;//总空间
}ST;
void Stackinit(ST**p);//初始化栈
void Stackdetroy(ST** p);//销毁栈
void Stackpush(ST** p, DATAtype x);//入栈
void Stackpop(ST** p);//出栈
int Stacksize(ST** p);//栈大小的返回
bool Stackempety(ST** p);//栈判空

2.初始化栈

我们这里初始化栈有 5个元素的大小空间,需要注意的是top的定义,因为在每次入栈之后top++,在进行打印时我们需要给它在减1,实现坐标的对应。top是当前元素的后一个元素的位置坐标,我们将这里定义为负1,打印时刚好打印a[0]元素,在进行迭代。

void Stackinit(ST* p)
{
  (p)->a = (DATAtype*)malloc(sizeof(DATAtype) * 5);
  (p)->capacity = 5;
  (p)->top = -1;//记录栈中数组位置
}

3.销毁栈

直接判空后free,在置为空。实现简单,不做赘述

//销毁栈
void Stackdetroy(ST* p)
{
  assert(p);
  free((p)->a);
  (p)->a = NULL;
  (p)->capacity = 0;
  (p)->top = 0;
}

4.入栈

入栈首先要对容量判断。因此这里还需要实现容量判断并扩容的操作,这里我直接定义一个函数。

入站的具体操作很简单,赋值并加加。

判断容量:

void chckcapacity(ST* p)
{
  //若容量不够,则扩容
  if ((p)->top == (p)->capacity)
  {
    DATAtype*tmp= (DATAtype*)realloc((p)->a,sizeof(DATAtype) * (p)->capacity * 2);
    if (tmp == NULL)
    {
      printf("realloc fail");
      return;
    }
    (p)->a = tmp;
    (p)->capacity = (p)->capacity * 2;
    printf("容量不够,已自动扩容,当前容量:%d\n", (p)->capacity);
  }
}

入栈:

void Stackpush(ST* p, DATAtype x)
{
  //检查容量
  chckcapacity(p);
  (p)->a[(p)->top] = x;
  (p)->top++;
}

5.出栈

操作也是简单,只要让数组访问不到即可,直接减减。

//出栈
void Stackpop(ST*p)
{
  (p)->top--;
  assert((p)->top);
  assert(p);
  //检查是否过量出栈
}

6.返回栈元素数量大小

很简单,返回top即可

//返回大小
int Stacksize(ST* p)
{
  assert(p);
  return (p)->top;
}

7.判空

bool Stackempety(ST* p)
{
  assert(p);
  if ((p)->top == NULL)
  {
    return true;
  }
  else
  {
    return false;
  }
}

8.打印栈

这个操作在定义top时需要注意一下,top是指向当前栈顶的下面那一个元素,在迭代打印时,注意访问是否越界的问题。

oid stackprintf(ST* p)
{
  assert(p);
  while ((p)->top>=0)
  {
    printf("%d->", (p)->a[(p)->top-1]);
    (p)->top--;
  }
}


相关文章
|
27天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
123 9
|
18天前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
22 1
|
5天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
26 5
|
20天前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
23天前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
25天前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
47 4
|
29天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
2月前
数据结构(栈与列队)
数据结构(栈与列队)
20 1
|
2月前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
72 1
|
2月前
【数据结构】-- 栈和队列
【数据结构】-- 栈和队列
17 0