用OC实现一个栈:结合单链表创建动态栈
一、介绍
栈是一种数据存储结构,存储的数据具有先进后出的特点。栈一般分为动态栈和静态栈。
静态栈比较好理解,例如用数组实现的栈。动态栈可以用链表来实现。
方式:固定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实现一个栈:结合单链表创建动态栈的更多相关文章
- python中栈的单链表实现
参考博客:https://www.cnblogs.com/stacklike/p/8284550.html 基于列表的简单实现 # 先进后出 # 以列表实现的简单栈 class SimpleStack ...
- C语言 - 栈和单链表的实现
单链表:linkList.h linkList.c #ifndef LINKLIST_H_INCLUDE #define LINKLIST_H_INCLUDE #include <Windows ...
- 线性表:实现单链表和子类栈(Stack)及单向队列(Queue) [C++]
刚刚开始学习c++.之前c的内容掌握的也不多,基本只是一本概论课的程度,以前使用c的struct写过的链表.用python写过简单的数据结构,就试着把两者用c++写出来,也是对c++的class,以及 ...
- java实现一个简单的单链表反转
自定义一个单链表,实现链表反转: 1.普通方法实现 2.递归方式实现 package listNode; public class ReverseNode { public static void m ...
- 单链表创建、删除、查找、插入之C语言实现
本文将详细的介绍C语言单链表的创建.删除.查找.插入以及输出功能 一.创建 #include<stdio.h> #include<stdlib.h> typedef int E ...
- Javascript - 栈 和 单链表
最近在重温数据结构,于是写了一些代码玩玩,都是很初级的,表喷各位.... function Stack() { this.dataStore = []; this.top = 0; } Stack.p ...
- 数据结构与算法——链表 Linked List(单链表、双向链表、单向环形链表-Josephu 问题)
链表是有序的列表,但是在内存中存储图下图所示 链表是以 节点 的方式来存储,是 链式存储 每个节点包含 data 域.next 域,指向下一个节点 链表的各个节点 不一定是连续存储,如上图所示 链表还 ...
- C++ "链链"不忘@必有回响之单链表
1. 前言 数组和链表是数据结构的基石,是逻辑上可描述.物理结构真实存在的具体数据结构.其它的数据结构往往在此基础上赋予不同的数据操作语义,如栈先进后出,队列先进先出-- 数组中的所有数据存储在一片连 ...
- C++实现简单的单链表
下面实现的是一个简单的单链表 功能不多,学习使用 #pragma once #include <iostream> using namespace std; class ListEx { ...
随机推荐
- 从0系统学Android--3.1编写UI界面
从0系统学Android--3.1编写UI界面 本系列文章目录:更多精品文章分类 本系列持续更新中.... 界面设计和功能开发同样重要,界面美观的应用程序不仅可以大大增加用户粘性,还能帮我们吸引到更多 ...
- Flink01
1. 什么是Flink? 1.1 4代大数据计算引擎 第一代: MapReducer 批处理 Mapper, Reducer Hadoop的MapReducer将计算分为两个阶段, 分别为Map和Re ...
- leetcode-10
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符'*' 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的 ...
- Java中dimension类详解
Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788
- 使用matplotlib.pyplot中scatter()绘制散点图
1.二维散点图 二维散点图的函数原型: matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=Non ...
- 架构组件:基于Shard-Jdbc分库分表,数据库扩容方案
本文源码:GitHub·点这里 || GitEE·点这里 一.数据库扩容 1.业务场景 互联网项目中有很多"数据量大,业务复杂度高,需要分库分表"的业务场景. 这样分层的架构 (1 ...
- Winform中使用DevExpress的CheckEdit控件实现多选条件搜索
场景 Winform控件-DevExpress18下载安装注册以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1 ...
- TortoiseSVN 无法查看日志 日期显示1970-01-01的解决方案
对有问题的目录, 在右键菜单中, 使用 TortoiseSVN 的 Revision Graph 命令, 等待该命令执行完毕, 再重新使用 Show Log 命令, 即可查看日志了
- golang中,new和make的区别
在golang中,make和new都是分配内存的,但是它们之间还是有些区别的,只有理解了它们之间的不同,才能在合适的场合使用. 简单来说,new只是分配内存,不初始化内存: 而make即分配又初始化内 ...
- python assert断言用法
作用:断言函数运行状态 语法:assert condition,判断condition运行状态,若condition状态为false,则上报错误:AssertionError