用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 { ...
随机推荐
- 列表list常用的方法
列表 name = ['Lisa', 'Mike', 'Jone', 'Lucy'] name.sort() # 排序,根据对应的ASCII码值,可以排各种类型的字符 name.append('Ms ...
- MATLAB实例:散点密度图
MATLAB实例:散点密度图 作者:凯鲁嘎吉 - 博客园http://www.cnblogs.com/kailugaji/ MATLAB绘制用颜色表示数据密度的散点图 数据来源:MATLAB中“fit ...
- Flutter中高级培训
Flutter中高级培训 一.简介 Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面.Flutter可以与现有的代码一起工作.本课程全面介绍Flutter ...
- Java连载55-Mail编程
一.电子邮件的历史 1.起源: 1969 Lenoard K. 教授发给同事的“LO” 1971 美国国防部自主的阿帕网(Arpanet)的通讯机制 通讯地址里用@ 1987年中国的第一份电子邮件 “ ...
- Linux下MySQL数据库的my.cnf配置文件,解决中文乱码问题
系统 CentOS 7.7 MySQL - 5.7.28文件放置目录:/etc/文件权限:644解决问题:存储中文数据乱码 # For advice on how to change settings ...
- 使用VBA从工作表中读图片,以及给工作表中写文件
因为工作的原因,需要用到VBA,碰到读图片和写图片: Sub Macro01() '从工作表中保存图片 Application.ScreenUpdating = False Dim pth, shp, ...
- windows本地连不上虚拟机redis服务完美解决
检查本机与虚拟机是否可以互相ping通,如本机IP:192.168.22.111 虚拟机IP:192.168.44.129 (设置虚拟机静态IP已设置) 本机 win+R 输入cmd 进入dos 输 ...
- SpringBoot2.0 基础案例(16):配置Actuator组件,实现系统监控
本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.Actuator简介 1.监控组件作用 在生产环境中,需要实时 ...
- 好用的js片段收藏
1.判断浏览器信息,如果是手机,就跳到手机页面 if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { wind ...
- (三十七)c#Winform自定义控件-有标题的面板-HZHControls
官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...