如果你能用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基础。