Last active
August 29, 2015 14:24
-
-
Save codetalks-new/b3bedbee22eb34c61f17 to your computer and use it in GitHub Desktop.
Swift 绘制二叉树类
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class TreeNode{ | |
let val:Int | |
var left:TreeNode? | |
var right:TreeNode? | |
init(val:Int){ | |
self.val = val | |
} | |
} | |
struct TreeNodeRect{ | |
let treeNode:TreeNode | |
let rect : CGRect | |
init(treeNode:TreeNode,rect:CGRect){ | |
self.treeNode = treeNode | |
self.rect = rect | |
} | |
var center:CGPoint{ | |
return rect.center | |
} | |
} | |
extension CGRect{ | |
init(center:CGPoint,radius:CGFloat){ | |
origin = CGPoint(x: center.x - radius, y: center.y - radius) | |
size = CGSize(width: radius, height: radius) | |
} | |
init(center:CGPoint,width:CGFloat, height:CGFloat){ | |
origin = CGPoint(x: center.x - width * 0.5, y: center.y - height * 0.5) | |
size = CGSize(width: width, height: height) | |
} | |
init(center:CGPoint,size:CGSize){ | |
origin = CGPoint(x: center.x - size.width * 0.5, y: center.y - size.height * 0.5) | |
self.size = size | |
} | |
var center:CGPoint{ | |
return CGPoint(x: minX + width * 0.5, y: minY + height * 0.5) | |
} | |
} | |
class BinaryTreeView: UIView{ | |
var binaryTree:TreeNode | |
var radius : CGFloat = 30 | |
var lineSpacing : CGFloat = 60 | |
var treeNodeRects:[TreeNodeRect] = [] | |
init(frame:CGRect,binaryTree:TreeNode){ | |
self.binaryTree = binaryTree | |
super.init(frame: frame) | |
backgroundColor = UIColor.whiteColor() | |
regenerateNodeList() | |
} | |
override func drawRect(rect: CGRect) { | |
let ctx = UIGraphicsGetCurrentContext() | |
let lineNodes = treeNodeRects | |
let nodeRectByNode = { | |
(node:TreeNode) -> TreeNodeRect? in | |
for nr in lineNodes{ | |
if nr.treeNode === node{ | |
return nr | |
} | |
} | |
return nil | |
} | |
let drawLineWithPoint = { | |
(from:CGPoint,to: CGPoint) -> Void in | |
CGContextMoveToPoint(ctx, from.x, from.y) | |
CGContextAddLineToPoint(ctx, to.x, to.y) | |
} | |
for nodeRect in lineNodes{ | |
let node = nodeRect.treeNode | |
if let left = node.left{ | |
if let leftRect = nodeRectByNode(left){ | |
drawLineWithPoint(nodeRect.center,leftRect.center) | |
} | |
} | |
if let right = node.right{ | |
if let rightRect = nodeRectByNode(right){ | |
drawLineWithPoint(nodeRect.center,rightRect.center) | |
} | |
} | |
} | |
CGContextStrokePath(ctx) | |
UIColor(white: 0.88, alpha: 1.0) | |
for nodeRect in treeNodeRects{ | |
CGContextFillEllipseInRect(ctx, nodeRect.rect) | |
} | |
for nodeRect in treeNodeRects{ | |
drawTextInRect(String(nodeRect.treeNode.val), rect: nodeRect.rect) | |
} | |
} | |
func drawTextInRect(text:String,rect:CGRect){ | |
let attrs = [NSForegroundColorAttributeName: UIColor.whiteColor(), | |
NSFontAttributeName: UIFont.systemFontOfSize(rect.height * 0.5) | |
] | |
let attributedText = NSMutableAttributedString(string: text,attributes: attrs) | |
let textSize = attributedText.size() | |
let textRect = CGRect(center: CGPoint(x: rect.midX, y: rect.midY), size:textSize) | |
attributedText.drawInRect(textRect) | |
} | |
private func regenerateNodeList(){ | |
treeNodeRects.removeAll() | |
arrangeTreeNode(binaryTree, inRect: bounds) | |
setNeedsDisplay() | |
} | |
func arrangeTreeNode(treeNode:TreeNode,inRect rect:CGRect){ | |
let nodeRect = CGRect(center: CGPoint(x: rect.midX, y: rect.minY + radius), radius: radius) | |
treeNodeRects.append(TreeNodeRect(treeNode: treeNode, rect: nodeRect)) | |
let childRect = rect.rectsByDividing(nodeRect.height + lineSpacing, fromEdge: .MinYEdge).remainder | |
let childRects = childRect.rectsByDividing(childRect.width * 0.5, fromEdge: .MinXEdge) | |
if let left = treeNode.left{ | |
arrangeTreeNode(left, inRect: childRects.slice) | |
} | |
if let right = treeNode.right{ | |
arrangeTreeNode(right, inRect: childRects.remainder) | |
} | |
} | |
required init(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
} | |
let binaryTree4 = createBinaryTree4() | |
let binaryTreeView = BinaryTreeView(frame: CGRect(x: 0, y: 0, width: 320, height: 480), binaryTree: binaryTree4) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment