从零开始学swift(五)-算法之利用栈实现二叉树遍历

如果你能用swift写出栈并利用其实现二叉树的遍历,我可以负责任地说,再学一些iOS基础,开发一款本地的简单app是绰绰有余了。不过你们想想,谁没事用swift实现这个遍历呢,诶下个月考托福,还要准备建模,我还有好多作业,先停更一个月,一个月足够让你从什么都不会到了解swift了。

开始正题,如何用swift实现stack,在苹果官网上面有,源码是这样滴

struct Stack<T> {
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    mutating func pop() -> T {
        return items.removeLast()
    }
}

还是比较简洁易懂的

接着我们在Stack里面写一个方法isEmpty()用来判断是否为空

    mutating func isEmpty()->Bool{
        if(items.isEmpty) {return true}
        else {return false}
    }

下面我们来借助之前的两节算法内容,利用栈实现二叉树三种遍历。

我们建树的方法跟之前基本一样,

func createTree(i:Int, n:Int)->UnsafeMutablePointer<Tree>?{//又有问号
    var p : UnsafeMutablePointer<Tree>?//又有问号
    if (i >= n) {return nil}
    p = UnsafeMutablePointer<Tree>.alloc(sizeof(Tree))
    p?.memory.data = random() % 6 + 1//又有问号//这里换了一种方法
    p?.memory.lchild = createTree(i*2+1, n)//又有问号
    p?.memory.rchild = createTree(i*2+2, n)//又有问号
    return p
}
前序和中序遍历跟C差不多

func preOrder(t : UnsafeMutablePointer<Tree>?){
    var stack = Stack<UnsafeMutablePointer<Tree>>()
    var tree = t
    while (tree != nil || !stack.isEmpty()){
        if(tree != nil){
            visited(tree!)
            stack.push(tree!)//入栈
            tree = tree?.memory.lchild
        }
        else{
            tree = stack.pop()//出栈
            tree = tree?.memory.rchild
        }
    }
}
func inOrder(t : UnsafeMutablePointer<Tree>?){
    var stack = Stack<UnsafeMutablePointer<Tree>>()
    var tree = t
    while (tree != nil || !stack.isEmpty()){
        if(tree != nil){
            stack.push(tree!)
            tree = tree?.memory.lchild
        }
        else{
            tree = stack.pop()
            visited(tree!)
            tree = tree?.memory.rchild
        }
    }
}
真正重头的是后续遍历,由于后续遍历要标记左右子树的状态,这样的话就不得不存储两个量,因此我想到的方法是建立一个存指针的2*1的矩阵,然后将矩阵压入stack

首先建立一个矩阵

struct TreeMatrix {
    let rows: Int, columns: Int
    var grid: [UnsafeMutablePointer<Tree>?]
    init() {
        self.rows = 2
        self.columns = 1
        grid = Array(count: rows * columns, repeatedValue: nil)
    }
    func indexIsValidForRow(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> UnsafeMutablePointer<Tree>?{
        get {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

然后我们重写一个Stack_2

struct Stack_2<T> {
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    mutating func pop() -> T {
        return items.removeLast()
    }
    mutating func isEmpty()->Bool{
        if(items.isEmpty) {return true}
        else {return false}
    }
    mutating func top()->T{
        return items.last!
    }
}

然后建立一个 boolTree,如果访问左右子树,则将矩阵里第二行的指针指向该树,用来判断状态,借此实现后续遍历

var boolTree : UnsafeMutablePointer<Tree>? = createTree(0, 1)
func postOrder(t : UnsafeMutablePointer<Tree>?){
    var stack = Stack_2<TreeMatrix>()
    var tree = TreeMatrix()
    tree[0,0] = t
    while (tree[0,0] != nil || !stack.isEmpty()){
        if(tree[0,0] != nil){
            stack.push(tree)
            tree[0,0] = tree[0,0]?.memory.lchild
        }
        else{
            if(stack.top()[1,0] == nil)
            {
                var tempTree = stack.pop()
                tempTree[1,0] = boolTree
                stack.push(tempTree)
                tree[0,0] = stack.top()[0,0]?.memory.rchild
            }
            else{
                visited(stack.pop()[0,0]!)
            }
        }
    }
}

这样就实现了后续遍历。还没有完,我想用swift输入一个整数,然后生成对应节点个数的二叉树,这就涉及到了swift的控制台输入,可惜呀,没找到,于是我决定用swift与oc混编实现(这就是swift的强大之处,我 swift可以用你的oc类)


选择new File


建立一个叫Read的类,在头文件里面加上

#import <Foundation/Foundation.h>
@interface Read: NSObject
-(int) readnum;
//-(int) read;
@end

.m文件加上

#import "Read.h"

@implementation Read
-(int) readnum
{
    int readNum;
    scanf ("%d", &readNum);
    return readNum;
    
}
@end

在另一个bridging-heading文件里面加上

#import "Read.h"

然后就可以调用了

我们在swift文件里面可以这么调用

var readNumber = Read()
var n : Int = Int(readNumber.readnum())
var newTree : UnsafeMutablePointer<Tree>? = createTree(0,n)

最后就是测试运行啦

preOrder(newTree!)
println()
inOrder(newTree!)
println()
postOrder(newTree!)

我们来看一下结果

输入6的话


到这里我们的算法就告一段落啦,一个月以后再开始写ios基础。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值