在iPhone上展示哈夫曼二叉树

来源:互联网 发布:js this用法 编辑:程序博客网 时间:2024/06/08 08:20


//

//  BTreeNode.h

//  Huffman

//

//  Created by zmx on 16/2/24.

//  Copyright © 2016 zmx. All rights reserved.

//


#import <Foundation/Foundation.h>


@interface BTreeNode : NSObject


@property (nonatomic,assign)int data;


@property (nonatomic,strong)BTreeNode *leftChild;

@property (nonatomic,strong)BTreeNode *rightChild;


@property (nonatomic,readonly,assign)int depth;

@property (nonatomic,readonly,assign)int maxNodeCount;


@end



//

//  BTreeNode.m

//  Huffman

//

//  Created by zmx on 16/2/24.

//  Copyright © 2016 zmx. All rights reserved.

//


#import "BTreeNode.h"


@implementation BTreeNode


- (int)depth {

    returnMAX(self.leftChild.depth,self.rightChild.depth) +1;

}


- (int)maxNodeCount {

    return pow(2,self.depth) -1;

}


@end



//

//  TreeView.h

//  Huffman

//

//  Created by zmx on 16/2/24.

//  Copyright © 2016 zmx. All rights reserved.

//


#import <UIKit/UIKit.h>


@class BTreeNode;


@interface TreeView : UIView


@property (nonatomic,strong)BTreeNode *tree;


@end



//

//  TreeView.m

//  Huffman

//

//  Created by zmx on 16/2/24.

//  Copyright © 2016 zmx. All rights reserved.

//


#import "TreeView.h"

#import "BTreeNode.h"


//  UIView+ZMX.h文件详细请见https://github.com/zmx6999/ZMXView/tree/master

#import "UIView+ZMX.h"


#define margin 10


#define nodeW ((ScreenW - margin * (self.tree.maxNodeCount + 1)) / self.tree.maxNodeCount)


#define maxNodeCenterHorizontalDistance ((ScreenW - nodeW - margin * 2) * 0.5)


@implementation TreeView



// Only override drawRect: if you perform custom drawing.

// An empty implementation adversely affects performance during animation.

- (void)drawRect:(CGRect)rect {

    // Drawing code

    [selfappendBTreeNode:self.treefloor:1center:CGPointMake(ScreenW /2, 60)];

}


- (void)setTree:(BTreeNode *)tree {

    _tree = tree;

    

    [selfsetNeedsDisplay];

}


- (void)appendBTreeNode:(BTreeNode *)treeNode floor:(int)floor center:(CGPoint)center {

    NSString *str = [NSStringstringWithFormat:@"%d", treeNode.data];

    UILabel *label = [[UILabelalloc]init];

    label.text = str;

    label.textColor = [UIColorblackColor];

    label.font = [UIFontsystemFontOfSize:12];

    

    label.bounds = CGRectMake(0, 0, nodeW, nodeW);

    label.center = center;

    label.textAlignment =NSTextAlignmentCenter;

    [self addSubview:label];

    

    CGFloat nodeCenterHorizontalDistance = maxNodeCenterHorizontalDistance * pow(0.5, floor);

    CGFloat nodeBorderHorizontalDistance = nodeCenterHorizontalDistance -nodeW;

    

    if (treeNode.leftChild) {

        UIBezierPath *path = [UIBezierPathbezierPath];

        CGPoint pointA = [UIViewleftBottomPointWithCenter:centerwidth:nodeW];

        [path moveToPoint:pointA];

        CGPoint pointB = [UIViewleftBottomPointWithPoint:pointAhorizontalDistance:nodeBorderHorizontalDistance];

        [path addLineToPoint:pointB];

        [path stroke];

        

        CGPoint leftCenter = [UIViewleftBottomPointWithPoint:centerhorizontalDistance:nodeCenterHorizontalDistance];

        [self appendBTreeNode:treeNode.leftChildfloor:floor +1center:leftCenter];

    }

    

    if (treeNode.rightChild) {

        UIBezierPath *path = [UIBezierPathbezierPath];

        CGPoint pointA = [UIViewrightBottomPointWithCenter:centerwidth:nodeW];

        [path moveToPoint:pointA];

        CGPoint pointB = [UIViewrightBottomPointWithPoint:pointAhorizontalDistance:nodeBorderHorizontalDistance];

        [path addLineToPoint:pointB];

        [path stroke];

        

        CGPoint rightCenter = [UIViewrightBottomPointWithPoint:centerhorizontalDistance:nodeCenterHorizontalDistance];

        [self appendBTreeNode:treeNode.rightChildfloor:floor +1center:rightCenter];

    }

}


@end





//

//  ViewController.m

//  Huffman

//

//  Created by zmx on 16/2/24.

//  Copyright © 2016 zmx. All rights reserved.

//


#import "ViewController.h"

#import "BTreeNode.h"

#import "TreeView.h"


#define N 5


@interface ViewController ()


@property (weak, nonatomic) IBOutletTreeView *treeView;


@property (nonatomic,strong)NSMutableArray *trees;


@end


@implementation ViewController


- (NSMutableArray *)trees {

    if (_trees ==nil) {

        _trees = [NSMutableArrayarray];

    }

    return _trees;

}


- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    int a[N] = {29,8,14, 7, 23};

    [selfinitTreesWithArray:a];

    [selfquickSortWithStart:0end:N -1];

    

    [selfcreateHuffmanTree];

    

    self.treeView.tree =self.trees.firstObject;

}


- (void)initTreesWithArray:(int *)a {

    for (int i =0; i <N; i++) {

        BTreeNode *tree = [[BTreeNodealloc]init];

        tree.data = a[i];

        tree.leftChild = nil;

        tree.rightChild = nil;

        [self.treesaddObject:tree];

    }

}


- (void)quickSortWithStart:(int)s end:(int)t {

    if (s >= t) {

        return;

    }

    

    BTreeNode *sTree = [self.treesobjectAtIndex:s];

    int k = sTree.data;

    int i = s;

    int j = t;

    

    while (i < j) {

        while (i < j) {

            BTreeNode *jTree = [self.treesobjectAtIndex:j];

            if (jTree.data >= k) {

                j--;

            } else {

                break;

            }

        }

        

        if (i < j) {

            [selfexchangeBTreeAtIndex:iwithBTreeAtIndex:j];

        }

        

        while (i < j) {

            BTreeNode *iTree = [self.treesobjectAtIndex:i];

            if (iTree.data <= k) {

                i++;

            } else {

                break;

            }

        }

        

        if (i < j) {

            [selfexchangeBTreeAtIndex:iwithBTreeAtIndex:j];

        }

    }

    

    [selfquickSortWithStart:send:i -1];

    [selfquickSortWithStart:i +1end:t];

}


- (void)exchangeBTreeAtIndex:(int)i withBTreeAtIndex:(int)j {

    BTreeNode *tree1 = [self.treesobjectAtIndex:i];

    BTreeNode *tree2 = [self.treesobjectAtIndex:j];

    

    tree1.data = tree1.data ^ tree2.data;

    tree2.data = tree1.data ^ tree2.data;

    tree1.data = tree1.data ^ tree2.data;

}


- (void)insertTree:(BTreeNode *)tree {

    for (int i =0; i <self.trees.count; i++) {

        BTreeNode *currentTree = [self.treesobjectAtIndex:i];

        if (currentTree.data > tree.data) {

            [self.treesinsertObject:treeatIndex:i];

            return;

        }

    }

    

    [self.treesaddObject:tree];

}


- (void)createHuffmanTree {

    if (self.trees.count <2) {

        return;

    }

    

    BTreeNode *tree1 = [self.treesobjectAtIndex:0];

    BTreeNode *tree2 = [self.treesobjectAtIndex:1];

    

    BTreeNode *tree = [[BTreeNodealloc]init];

    tree.data = tree1.data + tree2.data;

    tree.leftChild = tree1;

    tree.rightChild = tree2;

    

    [self.treesremoveObjectAtIndex:0];

    [self.treesremoveObjectAtIndex:0];

    [self insertTree:tree];

    

    [selfcreateHuffmanTree];

}


@end


0 0