-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path08_tree.c
145 lines (133 loc) · 4.14 KB
/
08_tree.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#ifndef NULL
# define NULL ((void *)0)
#endif
struct node
{
struct node *right;
struct node *left;
struct node *parent;
unsigned long value;
};
struct root
{
struct node *node;
};
struct node* search_node(struct root* root, unsigned long value);
#define parent(r) ((r)->parent)
/*@ //Find value in tree.
@ axiomatic rbtree_find_value {
@ logic struct node * find_in_tree{L}(struct node * node, integer value);
@
@ axiom present_in_given_node:
@ \forall struct node * node, integer value;
@ \valid(node) && node->value == value
@ ==> find_in_tree(node, value) == node;
@
@ axiom null_not_found:
@ \forall integer value;
@ find_in_tree(\null, value) == \null;
@
@ axiom left_child:
@ \forall struct node * node, integer value;
@ \valid(node) && node->value > value
@ ==> find_in_tree(node, value) == find_in_tree(node->left, value);
@
@ axiom right_child:
@ \forall struct node * node, integer value;
@ \valid(node) && node->value < value
@ ==> find_in_tree(node, value) == find_in_tree(node->right, value);
@ }
@
@ //Calc num of nodes
@ axiomatic rbtree_calc_size {
@ logic integer calc_size{L}(struct node * node);
@ axiom null_size:
@ calc_size(\null) == 0;
@ axiom not_null_size:
@ \forall struct node * node;
@ \valid(node) ==> (calc_size(node) == (1 + calc_size(node->left) + calc_size(node->right)));
@
@ axiom calc_size_child:
@ \forall struct node * node;
@ \valid(node) ==> ((calc_size(node) > calc_size(node->left)) && calc_size(node) > calc_size(node->right));
@
@ axiom calc_size_nonnegative:
@ \forall struct node * node;
@ \valid(node) ==> (calc_size(node) >= 0);
@ }
@ */
/* Tools workaround */
/*@
@ lemma valid_tools_workaround_nonull:
@ \forall struct node *node;
@ ((node != \null) ==> (\valid(node)));
@
@ lemma valid_tools_workaround_single_standalone:
@ \forall struct node *node;
@ (\valid(node) && node->parent != node) ==>
@ (node->parent->parent != node->parent);
@ */
/* Type invariants. */
/*@
@ lemma type_invariant_child_nodes:
@ \forall struct node * node;
@ \valid(node) && \valid(node->parent) ==>
@ (node == node->parent->left || node == node->parent->right);
@
@ // If given node has value less then parent node value, then
@ // it's left child for it's parent.
@ lemma type_invariant_node_values_parent_left:
@ \forall struct node * node;
@ (\valid(node) && \valid(parent(node))
@ ==>
@ ((parent(node)->value > node->value) <==>
@ (parent(node)->left == node)));
@
@ // If given node has value greater then parent node value, then
@ // it's right child for it's parent.
@ lemma type_invariant_node_values_parent_right:
@ \forall struct node * node;
@ (\valid(node) && \valid(parent(node))
@ ==>
@ ((parent(node)->value < node->value) <==>
@ (parent(node)->right == node)));
@
@ // Childler of given node have this node as parent.
@ lemma type_invariant_parent_child_left:
@ \forall struct node * node;
@ \valid(node) ==>
@ (\valid(node->left) ==> parent(node->left) == node);
@
@ lemma type_invariant_parent_child_right:
@ \forall struct node * node;
@ \valid(node) ==>
@ (\valid(node->right) ==> parent(node->right) == node);
@
@*/
/*@ // requires all type_invariants for root are true
requires \valid(root); // pointer is non-null
ensures \result == find_in_tree(root->node, value);
ensures \result != \null ==>
(
\valid(\result) &&
\result->value == value
);
*/
struct node* search_node(struct root* root, unsigned long value)
{
struct node* n = root->node;
/*@ loop invariant find_in_tree(root->node, value) == find_in_tree(n, value);
loop invariant find_in_tree(root->node, value) != \null ==> \valid(n);
loop variant (calc_size(n));
*/
while (n)
{
if (value < n->value)
n = n->left;
else if (value > n->value)
n = n->right;
else
return n;
}
return NULL;
}