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

来源:互联网 发布:人脸特征比对算法 编辑:程序博客网 时间:2024/06/05 20:02

如果你能用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
原创粉丝点击