一、介绍

栈是一种数据存储结构,存储的数据具有先进后出的特点。栈一般分为动态栈和静态栈。

静态栈比较好理解,例如用数组实现的栈。动态栈可以用链表来实现。

方式:固定base指针,每次更改top指向入栈的节点,遍历时从top节点遍历即可。

判空:s.top == s.base && s.top == nil && s.base == nil

栈满:s.top - s.base >= s.stackSize

三、图示

初始状态:s.top = s.base = nil,栈顶和栈底指针指向空,分配栈大小为s.stackSize = 4;

入栈状态:s.base不变,s.top = node,栈底指针不变,栈顶指针指向新节点

栈满状态:s.top - s.base >= s.stackSize, 遍历链表,链表的长度等于或大于栈大小

出栈状态:s.base不变,s.top = node->next,  node节点从链表断裂取出,top指针指向node下一个节点

栈空状态:s.top=nil,并将s.base=s.stop。

三、代码

node:

//  Node.h
// 运行时
//
// Created by 夏远全 on 2019/10/16.
// #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface Node : NSObject
@property (nonatomic, assign) int data;
@property (nonatomic, strong, nullable) Node *next;
-(instancetype)initWithData:(int)data;
@end NS_ASSUME_NONNULL_END
//  Node.m
// 运行时
//
// Created by 夏远全 on 2019/10/16. #import "Node.h" @implementation Node -(instancetype)initWithData:(int)data {
self = [super init];
if (self) {
self.data = data;
self.next = nil;
}
return self;
} @end

stack:

//
// Stack.h
// 运行时
//
// Created by 夏远全 on 2019/10/16.
// #import <Foundation/Foundation.h>
#import "Node.h" NS_ASSUME_NONNULL_BEGIN /*
特点:栈是先进后出的特点,采用链表实现一个动态栈(静态栈可以用数组实现)。固定base指针,每次更改top指向入栈的节点,遍历时从top节点遍历即可。 链表栈
判空:s.top == s.base && s.top == nil && s.base == nil
栈满:s.top - s.base >= s.stackSize
*/ @interface Stack : NSObject /**
构造一个栈
@return 栈
*/
+(instancetype)constructStack; /**
推入一个节点
@param node 节点
*/
-(void)pushNode:(Node *)node; /**
推出一个节点
*/
-(void)pop; @end NS_ASSUME_NONNULL_END
//
// Stack.m
// 运行时
//
// Created by 夏远全 on 2019/10/16.
// #import "Stack.h" @interface Stack ()
@property (nonatomic, strong) Node *top; //栈顶指针
@property (nonatomic, strong) Node *base; //栈底指针
@property (nonatomic, assign) int stackSize; //栈初始大小
@end @implementation Stack +(instancetype)constructStack
{
Stack *stack = [[Stack alloc] init];
stack.top = stack.base;
stack.stackSize = ;
return stack;
} -(void)pushNode:(Node *)node { //空节点
if (!node) {
NSLog(@"------不能push一个空的节点-------");
return;
} //栈满
if ([self isFull]) {
NSLog(@"------栈已满-------,当前节点node值: %d不能被push", node.data);
[self printStack];
return;
} //修改栈顶指针,确定栈底指针,不会再改变
if ([self isEmpty]) {
self.top = self.base = node;
}
else{
node.next = self.top;
self.top = node;
}
NSLog(@"push入栈的节点:data = %d", node.data);
} -(void)pop { //栈为空
if ([self isEmpty]) {
NSLog(@"------栈已空-------");
return;
} //删除节点,并修改栈顶指针
Node *popNode = self.top;
self.top = popNode.next;
NSLog(@"pop出栈的节点:data = %d",popNode.data); //节点pop完毕
if (self.top == nil) {
self.base = self.top;
NSLog(@"------栈已空-------");
}
} -(BOOL)isEmpty {
return (self.top == self.base && self.top == nil && self.base == nil);
} -(BOOL)isFull { //遍历长度
int size = ;
Node *p = self.top;
while (p != nil) {
size ++;
p = p.next;
}
return size >= self.stackSize;
} -(void)printStack { NSMutableArray *nodes = [NSMutableArray array];
Node *p = self.top;
while (p != nil) {
[nodes addObject:@(p.data)];
p = p.next;
}
NSLog(@"当前栈的所有节点为:%@",[nodes componentsJoinedByString:@"->"]);
} @end

四、打印

-(void)test_DataStructure_Stack {

    /// 构造栈
Stack *stack = [Stack constructStack]; /// 构造元素
Node *node1 = [[Node alloc] initWithData:];
Node *node2 = [[Node alloc] initWithData:];
Node *node3 = [[Node alloc] initWithData:];
Node *node4 = [[Node alloc] initWithData:];
Node *node5 = [[Node alloc] initWithData:];
Node *node6 = [[Node alloc] initWithData:]; /// push时,进去的顺序为: 1、2、3、4、5
[stack pushNode:node1];
[stack pushNode:node2];
[stack pushNode:node3];
[stack pushNode:node4];
[stack pushNode:node5];
[stack pushNode:node6];//node6不能被push进去,栈已满 /// pop时,出来的顺序为: 5、4、3、2、1
[stack pop];
[stack pop];
[stack pop];
[stack pop];
[stack pop];//最后一个节点被pop出来,栈已空
}
-- ::03.214331+ 运行时[:] push入栈的节点:data =
-- ::03.214513+ 运行时[:] push入栈的节点:data =
-- ::03.214620+ 运行时[:] push入栈的节点:data =
-- ::03.214715+ 运行时[:] push入栈的节点:data =
-- ::03.214796+ 运行时[:] push入栈的节点:data =
-- ::03.214878+ 运行时[:] ------栈已满-------,当前节点node值: 6不能被push
-- ::03.215023+ 运行时[:] 当前栈的所有节点为:->->->->
-- ::03.215111+ 运行时[:] pop出栈的节点:data =
-- ::03.215208+ 运行时[:] pop出栈的节点:data =
-- ::03.215508+ 运行时[:] pop出栈的节点:data =
-- ::03.215845+ 运行时[:] pop出栈的节点:data =
-- ::03.216101+ 运行时[:] pop出栈的节点:data =
-- ::03.216429+ 运行时[:] ------栈已空-------

用OC实现一个栈:结合单链表创建动态栈的更多相关文章

  1. python中栈的单链表实现

    参考博客:https://www.cnblogs.com/stacklike/p/8284550.html 基于列表的简单实现 # 先进后出 # 以列表实现的简单栈 class SimpleStack ...

  2. C语言 - 栈和单链表的实现

    单链表:linkList.h linkList.c #ifndef LINKLIST_H_INCLUDE #define LINKLIST_H_INCLUDE #include <Windows ...

  3. 线性表:实现单链表和子类栈(Stack)及单向队列(Queue) [C++]

    刚刚开始学习c++.之前c的内容掌握的也不多,基本只是一本概论课的程度,以前使用c的struct写过的链表.用python写过简单的数据结构,就试着把两者用c++写出来,也是对c++的class,以及 ...

  4. java实现一个简单的单链表反转

    自定义一个单链表,实现链表反转: 1.普通方法实现 2.递归方式实现 package listNode; public class ReverseNode { public static void m ...

  5. 单链表创建、删除、查找、插入之C语言实现

    本文将详细的介绍C语言单链表的创建.删除.查找.插入以及输出功能 一.创建 #include<stdio.h> #include<stdlib.h> typedef int E ...

  6. Javascript - 栈 和 单链表

    最近在重温数据结构,于是写了一些代码玩玩,都是很初级的,表喷各位.... function Stack() { this.dataStore = []; this.top = 0; } Stack.p ...

  7. 数据结构与算法——链表 Linked List(单链表、双向链表、单向环形链表-Josephu 问题)

    链表是有序的列表,但是在内存中存储图下图所示 链表是以 节点 的方式来存储,是 链式存储 每个节点包含 data 域.next 域,指向下一个节点 链表的各个节点 不一定是连续存储,如上图所示 链表还 ...

  8. C++ "链链"不忘@必有回响之单链表

    1. 前言 数组和链表是数据结构的基石,是逻辑上可描述.物理结构真实存在的具体数据结构.其它的数据结构往往在此基础上赋予不同的数据操作语义,如栈先进后出,队列先进先出-- 数组中的所有数据存储在一片连 ...

  9. C++实现简单的单链表

    下面实现的是一个简单的单链表 功能不多,学习使用 #pragma once #include <iostream> using namespace std; class ListEx { ...

随机推荐

  1. 通过U盘在物理机安装CentOS出现Timeout的问题

    错误信息:centos dracut timeout..... 解决方案: 在进入install页面是,按e,启动编辑.要保证Label与U盘的卷标保持一致即可.

  2. 任正非讲话稿 PDF整理版

    任正非讲话稿 PDF整理版 任正非思想之路 这里收录了任正非讲话稿400余篇,从1994年到2018年,从深圳.中国到东南亚.非洲.欧洲.美洲,从研发.市场.服务到财经.人力资源.战略.内控与公共关系 ...

  3. bat批处理执行python 的几种方式

    第一种方式:@echo off C: cd C:\Users\administrator\Desktopstart python apidemo.py exit第二种方式: start cmd /K ...

  4. 默认值操作符(Freemarker的空值处理)

    默认值操作符: 使用形式例如: userName!default_expr 或 userName! 或 (userName)!default_expr 或 (userName)! 这个操作符允许你为可 ...

  5. spring boot 加入mail邮件支持

    一.添加依赖 <!-- 邮件整合 --> <dependency> <groupId>org.springframework.boot</groupId> ...

  6. java执行-cp报错 error: could not load JDBC driver

    首先查看对应的 jar 包是否存在,然后看一下 Server (获取数据库驱动类的名称 driverClassName)是否正确 例如: java -

  7. Python语法速查: 12. 文件与输入输出

    返回目录 (1)文件基本操作 ● 文件常用操作 内置函数或方法 描述 open(name [,mode [,buffering]]) 内置函数.用来打开文件,返回一个文件对象(file对象).详见下述 ...

  8. LeetCode刷题--两数相加(中等)

    题目描述 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表 ...

  9. quarter软件的破解

    链接;http://www.openedv.com/forum.php?mod=viewthread&tid=275857&extra=page%3D1 这个是正点原子提供的破解方法, ...

  10. enter键的使用

    vue全部的按键别名: .enter .tab .delete (捕获“删除”和“退格”键) .esc .space .up .down .left .right vue中 <input v-o ...