Objective-C中的二进制树

前端之家收集整理的这篇文章主要介绍了Objective-C中的二进制树前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在学习算法和数据结构,并训练我正在使用 objective-c来设计和实现二叉树.

到目前为止,我有以下课程:

>主要 – 用于测试
>节点 – 树的节点
> BinaryTree – 用于与树相关的所有方法

我实现的BinaryTree类中的第一种方法之一是insertNode:forRoot :.

- (void)insertNodeByRef:(Node **)node forRoot:(Node **)root{

    if (head == NULL) {
        head = *node;
    }
    // Case 2 root is null so can assign the value of the node to it
    if (root == NULL) {
        root = node;
    } else {
        if (node.data > root.data) { // to the right
            [self insertNode:node forRoot:root.right];
        } else if (node.data < root.data) { //or to the left
            [self insertNode:node forRoot:root.left];
        }
    }
}

Node类的接口如下所示:

@interface Node : NSObject

@property(nonatomic,assign) int data;
@property(nonatomic,strong) Node * right;
@property(nonatomic,strong) Node * left;

@end

我的问题是,如果我传递Node作为参考,我不知道如何访问Node类成员变量.每当我尝试访问节点属性(如数据,左或右)时,我收到以下错误消息:

Member reference base type 'Node *__autoreleasing *' is not a structure or union

所以我的问题是:
如何访问这些属性(数据,左或右),并使用它们存储int数据或引用到另一个Node?

希望是有道理的.谢谢!

解决方法

你的代码正在混合两个常见的方法解决这个问题.您也使用抽象数据类型(ADT)类型方法,而不是面向对象的方法,因此有三种方法可以考虑.

在这两个ADT方法中,您的树都以对其根的引用表示,在Objective-C中,这可能存储在一个实例变量中:

Node *TreeRoot;

还要注意,这两种算法都使用字段引用a-> b而不是属性引用a.b – 这是因为前者引用了变量,第二种算法需要传递对变量的引用.

功能ADT:传递值并分配结果

在这种方法中,将节点插入到树中,并且返回被修改的树,例如.插入节点NodeToInsert的顶级调用将是:

TreeRoot = insertNode(nodeToInsert,TreeRoot);

并且insertNode函数看起来像:

Node *insertNode(Node *node,Node *root)
{
   if(root == nil)
   {  // empty tree - return the insert node
      return node;
   }
   else
   {  // non-empty tree,insert into left or right subtree
      if(node->data > root->data) // to the right
      {
        root->right = insertNode(node,root->right);
      }
      else if(node->data < root->data)//or to the left
      {
        root->left = insertNode(node,root->left);
      }
      // tree modified if needed,return the root
      return root;
   }
}

请注意,在这种方法中,在非空(子)树的情况下,算法对变量执行冗余分配 – 分配的值是已经在变量中的…因为这样,有些人更喜欢:

程序性ADT:通过参考

在这种方法中,保存(子)树的根的变量是通过引用传递的,而不是被传递的值,并且根据需要被调用的过程修改.例如.顶级电话将是:

insertNode(nodeToInsert,&TreeRoot); // & -> pass the variable,not its value

并且insertNode过程如下所示:

void insertNode(Node *node,Node **root)
{
   if(*root == nil)
   {  // empty tree - insert node
      *root = node;
   }
   else
   {  // non-empty tree,insert into left or right subtree
      Node *rootNode = *root;
      if(node->data > rootNode->data) // to the right
      {
        insertNode(node,&rootNode->right);
      }
      else if(node->data < rootNode->data)//or to the left
      {
        insertNode(node,&root->left);
      }
   }
}

您现在可以看到,您的方法是上述两种方法的混合体.两者都是有效的,但是正如您使用Objective-C一样,最好采用第三种方法

面向对象的ADT

这是程序ADT的一个变体 – 而不是将变量传递给一个过程,变量(现在称为对象)拥有一个更新自身的方法.这样做意味着您必须在进行呼叫插入节点之前测试一个空(子)树,而前两种方法调用中进行测试.所以现在我们在Node中有这个方法

- (void) insert:(Node *)node
{
   if(node.data > self.data) // using properties,could also use fields ->
   {
      if(self.right != nil)
         [self.right insert:node];
      else
         self.right = node;
   }
   else if(node.data < rootNode.data)
   {
      if(self.left != nil)
         [self.left insert:node];
      else
         self.left = node;
   }
}

您还需要更改顶级调用以对空树执行相同的测试:

if(TreeRoot != nil)
   [TreeRoot insert:nodeToInsert];
else
   TreeRoot = nodeToInsert;

最后一个注释 – 如果您使用MRC而不是ARC或GC进行内存管理,则需要插入适当的保留/释放调用.

希望能帮助你整理事情.

猜你在找的C&C++相关文章