I am struggeling with this:
I want to
(I need a recursive approach)
How can I fix the problem, that my program is only assigning values and inserting notes to the left? I know WHY it's not working. I just dont know what else to do.
How can i make it possible, that after inserting/assigning on the left, it heads to the right child and does the same thing all the time and not only in the first recursion?
Thank you so much in advance! Let me know if I need to specify anything.
EDIT: the input string will be an expression of the form ((3*(4+7)):((4+2)*(3-1))) for example. (the outer brackets will always be there)
Here is what I tried:
recursive subroutine split(str)
character(len=80):: str
type(tree),pointer:: point
allocate(point)
point%expression = str
call find_bracket(point%expression)
if(found_bracket) then !it searches for a ")" bracket
allocate(point%left)
allocate(point%right)
call find_zero_niveau(str)
call empty_slots(str)
point%left%expression = str(2 : zero_niv - 2) !assigning the new values
point%right%expression = str(zero_niv : 80 - spaces - 1)
point%expression = str(zero_niv - 1 : zero_niv - 1 )
point => point%left
call split(point%expression)
point => point%right
call split(point%expression) ! this obviously will not work
end if
end subroutine split
tree is defined like this:
type tree
character(len=80)::expression
type(tree), pointer::left,right
end type tree
subroutine find_zero_niveau(str)
character(len=80)::str
integer::j, bracket_niv
logical::bracket_check = .false.
call empty_slots(str)
j = 80 - spaces
bracket_niv = 0
do while (j >= 1)
j = j - 1
call getnextchar(str,j)
if (next_char == ")") then
bracket_check = .true.
bracket_niv = bracket_niv + 1
else if (next_char == "(") then
bracket_niv = bracket_niv - 1
end if
if (bracket_niv == 0 .and. bracket_check) then
zero_niv = j
exit
end if
end do
end subroutine find_zero_niveau
subroutine empty_slots(str)
character(len=80)::str
integer::i
spaces = 0
do i=1,80
call getnextchar(str,i) !getnextchar just extracts a value from the string
if (next_char == " ") then
spaces = spaces + 1
else if (next_char /= " ") then
spaces = 0
end if
end do
end subroutine empty_slots
As I said in a commment, I can't see how your routine could create a tree at all. At each call you are creating and allocating a point
variable, which is local and therefore destroyed once the routine returns. The current node of the tree should be passed as an argument to the routine, and you should have the following structure:
recursive subroutine split(point)
implicit none
type(tree), intent(inout) :: point
call find_bracket(point%expression)
if(found_bracket) then
call find_zero_niveau(point%expression)
call empty_slots(point%expression)
allocate(point%left)
point%left%expression = str(2 : zero_niv - 2)
call split(point%left)
allocate(point%right)
point%right%expression = str(zero_niv : 80 - spaces - 1)
call split(point%right)
point%expression = point%expression(zero_niv - 1 : zero_niv - 1 )
end if
end subroutine split
The head of the tree should be created before the first call:
type(tree), pointer :: head
allocate(head)
head%expression = initial_expression
call split(head)
More generally it seems that you are using many global variables, which is highly error-prone when dealing with recursive routines. Pass the variables as arguments as much as possible, and do not use global variables unless you have a good reason to do so.
Finally, you may replace all the pointer
attributes by allocatable
attributes. The advantage is that allocatable components are automatically deallocated when going out of scope, for instance here to destroy the tree you would just have to deallocate the head and all the nodes would be automatically and recursively deallocated. In the case you want to keep pointers, you should initialize them in the type description:
type tree
character(len=80) :: expression
type(tree), pointer :: left => null(), &
right => null()
end type tree