是否可以在没有指针的情况下在C中编写二进制搜索树?
我使用指针编写如下。
使用指针在C中使用BST代码
#include <stdio.h>
#include <malloc.h>
typedef struct node
{
int data;
struct node* left;
struct node* right;
}Node;
Node* root = NULL;
int insert(int);
int display(Node*);
int main(void)
{
int n = 0;
while(1)
{
printf("Enter data : ");
scanf("%d",&n);
if(n == -1)
break;
insert(n);
}
display(root);
return 0;
}
int insert(int data)
{
Node* node = malloc(sizeof(Node));
node->data = data;
node->left = NULL;
node->right = NULL;
Node* parent;
Node* trav;
if(root == NULL)
root = node;
else
{
trav = root;
while(trav != NULL)
{
parent = trav;
if(node->data < trav->data)
trav = trav->left;
else
trav = trav->right;
}
if(node->data < parent->data)
parent->left = node;
else
parent->right = node;
}
}
int display(Node* node)
{
if(node == NULL)
return 0;
display(node->left);
printf("%d ",node->data);
display(node->right);
}
是否可以在没有指针的情况下编写BST,并且只能使用节点。所以,我想以node.left而不是node-&gt; left来访问左边,依此类推。甚至结构节点的成员也应该像
typedef struct node
{
int data;
struct node left;
struct node right;
}Node;
并且Node成员将被声明为
Node root; Node node;
而不是
Node* root; Node* node;
如果使用上述结构无法编写BST,为什么会如此呢?是因为,NULL是指针,它具有保留的值,用于指示指针不引用有效对象。所以,如果我们只使用一个结构,我们就不知道何时停止。所以,我在上面的代码中注释掉了NULL行,并对访问作为结构成员而不是指针进行了更改。我期待它至少编译,虽然它会在一些地方无限循环。但是,它也给我一些编译错误。
在不使用指针的情况下在C中尝试BST代码,不编译
#include <stdio.h>
#include <malloc.h>
typedef struct node
{
int data;
struct node left;
struct node right;
}Node;
//Node root = NULL;
Node root;
int insert(int);
int display(Node);
int rootformed = 0;
int main(void)
{
int n = 0;
while(1)
{
printf("Enter data : ");
scanf("%d",&n);
if(n == -1)
break;
insert(n);
}
display(root);
return 0;
}
int insert(int data)
{
Node node = malloc(sizeof(Node));
node.data = data;
node.left = NULL;
node.right = NULL;
Node parent;
Node trav;
if(rootformed == 0)
{
root = node;
rootformed = 1;
}
else
{
trav = root;
//while(trav != NULL)
while(1)
{
parent = trav;
if(node.data < trav.data)
trav = trav.left;
else
trav = trav.right;
}
if(node.data < parent.data)
parent.left = node;
else
parent.right = node;
}
}
int display(Node node)
{
//if(node == NULL)
//return 0;
display(node.left);
printf("%d ",node.data);
display(node.right);
}
但是,我正在研究如何在Java中实现二进制搜索树,如下所示。如下所示,使用点符号访问成员。我很想知道它是如何在这里完成的。
如果class是一个结构,我可以说一个对象是一个指针 结构体。唯一的区别是在C中,指向a的指针 结构使用符号 - &gt;访问的内部成员 结构,而一个对象只是使用。访问内部 结构的成员(班级)
使用java中的工作BST代码。让我思考如何在C语言中使用它来表达。符号而不是 - &gt;
public class BinarySearchTree
{
public Node root;
public BinarySearchTree()
{
this.root = null;
}
public boolean find(int id)
{
Node current = root;
while(current!=null)
{
if(current.data == id)
{
return true;
}
else if(id < current.data)
{
current = current.left;
}
else
{
current = current.right;
}
}
return false;
}
public boolean delete(int id)
{
Node parent = root;
Node current = root;
boolean isLeftChild = false;
while(current.data != id)
{
parent = current;
if(id < current.data)
{
isLeftChild = true;
current = current.left;
}
else
{
isLeftChild = false;
current = current.right;
}
if(current ==null)
{
return false;
}
}
//if i am here that means we have found the node
//Case 1: if node to be deleted has no children
if(current.left==null && current.right==null)
{
if(current==root)
{
root = null;
}
if(isLeftChild ==true)
{
parent.left = null;
}
else
{
parent.right = null;
}
}
//Case 2 : if node to be deleted has only one child
else if(current.right==null)
{
if(current==root)
{
root = current.left;
}
else if(isLeftChild)
{
parent.left = current.left;
}
else
{
parent.right = current.left;
}
}
else if(current.left==null)
{
if(current==root)
{
root = current.right;
}
else if(isLeftChild)
{
parent.left = current.right;
}
else
{
parent.right = current.right;
}
}
else if(current.left!=null && current.right!=null)
{
//now we have found the minimum element in the right sub tree
Node successor = getSuccessor(current);
if(current==root)
{
root = successor;
}
else if(isLeftChild)
{
parent.left = successor;
}
else
{
parent.right = successor;
}
//successor.left = current.left;
}
return true;
}
public Node getSuccessor(Node deleteNode)
{
Node successsor =null;
Node successsorParent =null;
Node current = deleteNode.right;
while(current!=null)
{
successsorParent = successsor;
successsor = current;
current = current.left;
}
//check if successor has the right child, it cannot have left child for sure
//if it does have the right child, add it to the left of successorParent.
//successsorParent
if(successsor!=deleteNode.right)
{
successsorParent.left = successsor.right;
successsor.right = deleteNode.right;
}
if(successsor==deleteNode.right)
{
/* Then no more right tree */
}
successsor.left = deleteNode.left;
return successsor;
}
public void insert(int id)
{
Node newNode = new Node(id);
if(root==null)
{
root = newNode;
return;
}
Node current = root;
Node parent = null;
while(true)
{
parent = current;
if(id < current.data)
{
current = current.left;
if(current==null)
{
parent.left = newNode;
return;
}
}
else
{
current = current.right;
if(current==null)
{
parent.right = newNode;
return;
}
}
}
}
public void display(Node root)
{
if(root != null)
{
display(root.left);
System.out.print(" " + root.data);
display(root.right);
}
}
public static void main(String arg[])
{
BinarySearchTree b = new BinarySearchTree();
b.insert(3);b.insert(8);
b.insert(1);b.insert(4);b.insert(6);b.insert(2);b.insert(10);b.insert(9);
b.insert(20);b.insert(25);b.insert(15);b.insert(16);
System.out.println("Original Tree : ");
b.display(b.root);
System.out.println("");
System.out.println("Check whether Node with value 4 exists : " + b.find(4));
System.out.println("Delete Node with no children (2) : " + b.delete(2));
b.display(root);
System.out.println("\n Delete Node with one child (4) : " + b.delete(4));
b.display(root);
System.out.println("\n Delete Node with Two children (10) : " + b.delete(10));
b.display(root);
}
}
class Node
{
int data;
Node left;
Node right;
public Node(int data)
{
this.data = data;
left = null;
right = null;
}
}
答案 0 :(得分:3)
除了指向内存对象的指针外,您还可以在Node
和left
成员中分配大量right
个对象并将索引存储到此数组中。
数组条目0
是根节点。您必须跟踪第一个未使用的数组元素以存储新的Node
。您可以使用calloc
分配数组,使用realloc
扩大数组。
您必须跟踪已删除的项目:跟踪第一个项目,并将left
下一个已删除项目的索引(链接列表类型)放入。您还可以跟踪上次删除的项目,以快速将另一个已删除的iem附加到列表中。
答案 1 :(得分:0)
您可以使用数组索引而不是指针在数组中实现二进制搜索。在C中,数组只是一种语言结构,可以自动执行指针算法并使其不受代码限制。如果你对整个结构数组进行malloc并使左右成员整数具有一些合适的大小,它就可以工作。
但是在使用malloc单独创建的结构中,你无法在没有指针的情况下完成它,因为......
在C中,结构只是在连续块中分配的内存。的。运算符转换为块开头的简单偏移量。
当你尝试使用时。运算符引用.left或.right你指的是用不同的malloc创建的不同结构,它可以在堆内存中的任何位置。因此,从当前节点开始的简单偏移是未知的。
所以在C中你需要一个指针来存储左或右节点的地址。
在Java中,这些是对象引用,基本上是很好的包装和管理指针。 JVM正在管理分配和跟踪内存地址,这对您的代码来说几乎是透明的。实际上,您在运行时使用Java代码中的指针,但源代码是根据对象引用编写的。
您还可以使用文件或内存映射文件在C中实现二进制搜索,使用偏移到该文件而不是C指针。这可能不是您在问题中的意图,但通常是在需要二进制搜索的大型排序数据集的应用程序中完成的。