用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 = 5;
    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 = 0;
    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:1];
    Node *node2 = [[Node alloc] initWithData:2];
    Node *node3 = [[Node alloc] initWithData:3];
    Node *node4 = [[Node alloc] initWithData:4];
    Node *node5 = [[Node alloc] initWithData:5];
    Node *node6 = [[Node alloc] initWithData:6];
    
    /// 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出来,栈已空
}
2019-10-16 15:05:03.214331+0800 运行时[29420:1007559] push入栈的节点:data = 1
2019-10-16 15:05:03.214513+0800 运行时[29420:1007559] push入栈的节点:data = 2
2019-10-16 15:05:03.214620+0800 运行时[29420:1007559] push入栈的节点:data = 3
2019-10-16 15:05:03.214715+0800 运行时[29420:1007559] push入栈的节点:data = 4
2019-10-16 15:05:03.214796+0800 运行时[29420:1007559] push入栈的节点:data = 5
2019-10-16 15:05:03.214878+0800 运行时[29420:1007559] ------栈已满-------,当前节点node值: 6不能被push
2019-10-16 15:05:03.215023+0800 运行时[29420:1007559] 当前栈的所有节点为:5->4->3->2->1
2019-10-16 15:05:03.215111+0800 运行时[29420:1007559] pop出栈的节点:data = 5
2019-10-16 15:05:03.215208+0800 运行时[29420:1007559] pop出栈的节点:data = 4
2019-10-16 15:05:03.215508+0800 运行时[29420:1007559] pop出栈的节点:data = 3
2019-10-16 15:05:03.215845+0800 运行时[29420:1007559] pop出栈的节点:data = 2
2019-10-16 15:05:03.216101+0800 运行时[29420:1007559] pop出栈的节点:data = 1
2019-10-16 15:05:03.216429+0800 运行时[29420:1007559] ------栈已空-------

 

 

 

 

posted @ 2019-10-16 15:07  XYQ全哥  阅读(546)  评论(0编辑  收藏  举报