Reverse linked list in Ada - list

so as you can see I am trying to make a procedure to reverse a linked list, here is the code and the records of the list and the node, I am only obtaining the first number of the list and I think that it could be because pre is null and the head (Current) is pointing to null but I am not sure and I do not know how to solve this, thank you.
Type Node;
Type List is access Node;
Type Node is record
Info: Integer;
nx: List;
end record;
procedure reverselist (L: in out List) is
Current: List:=L ;
Pre: List:=null;
Next: List:=null;
begin
if Current.nx /= null then
while Current.nx /= null loop
Next:= Current.nx;
Current.nx:= Pre;
Pre:= Current;
Current:= Next;
end loop;
end if;
end reverselist;

I would start by just popping the head off the list repeatedly and building it back in reverse order:
procedure Reverse_List (L : in out list) is
Temp : List := null; -- Holds a "popped" head
Head : List := null; -- This is the head of the reversed list
begin
while L /= null loop
Temp := L; -- Pop the head of the list off
L := L.nx; -- Set the list head to the next item
Temp.nx := Head; -- Attach the popped node to the reversed head
Head := Temp; -- Reset the reverse head to the new node
end loop;
L := Head; -- Now set the input list pointer to the newly reversed list
end Reverse_List;
Full test program:
with Ada.Text_IO; use Ada.Text_IO;
procedure Hello is
Type Node;
Type List is access Node;
Type Node is record
Info: Integer;
nx: List;
end record;
procedure Reverse_List (L : in out list) is
Temp : List := null; -- Holds a "popped" head
Head : List := null; -- This is the head of the reversed list
begin
while L /= null loop
Temp := L; -- Pop the head of the list off
L := L.nx; -- Set the list head to the next item
Temp.nx := Head; -- Attach the popped node to the reversed head
Head := Temp; -- Reset the reverse head to the new node
end loop;
L := Head; -- Now set the input list pointer to the newly reversed list
end Reverse_List;
nodes : array (1..5) of List :=
(new Node'(Info => 1, nx =>null),
new Node'(Info => 2, nx =>null),
new Node'(Info => 3, nx =>null),
new Node'(Info => 4, nx =>null),
new Node'(Info => 5, nx =>null));
procedure Print(L : List) is
C : List := L;
begin
while C /= null loop
Put_Line(C.Info'Image);
C := C.nx;
end loop;
end Print;
L : List := nodes(1);
begin
Put_Line("Hello, world!");
nodes(1).nx := nodes(2);
nodes(2).nx := nodes(3);
nodes(3).nx := nodes(4);
nodes(4).nx := nodes(5);
Put_Line("Before:");
Print(L);
New_Line(2);
Put_Line("After:");
Reverse_List(L);
Print(L);
end Hello;
Output:
$gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello
$hello
Hello, world!
Before:
1
2
3
4
5
After:
5
4
3
2
1

if Current /= null then
while Current.nx /= null loop
Next:= Current.nx;
Current.nx:= Pre;
Pre:= Current;
Current:= Next;
end loop;
Next:= null;
Current.nx:= Pre;
L:= Current;
end if;

Going forward, also consider the convenience of a doubly linked list such as Ada.Containers.Doubly_Linked_Lists. Given an instance of the package for Integer,
package Integer_Lists is new Doubly_Linked_Lists (Integer);
use Integer_Lists;
A Reverse_List procedure can traverse the list in reverse, as discussed in Iteration, to create a new reversed list. Compare this approach to #Jere's Reverse_List.
procedure Reverse_List (L : in out List) is
T : List;
begin
for E of reverse L loop
T.Append (E);
end loop;
L := T;
end Reverse_List;
As an alternative to copying elements, the package also offers Reverse_Elements, which "Reorders the elements of Container in reverse order."
Reverse_Elements (L);
Complete example:
with Ada.Containers.Doubly_Linked_Lists; use Ada.Containers;
with Ada.Text_IO; use Ada.Text_IO;
procedure DLL is
package Integer_Lists is new Doubly_Linked_Lists (Integer);
use Integer_Lists;
procedure Reverse_List (L : in out List) is
T : List;
begin
for E of reverse L loop
T.Append (E);
end loop;
L := T;
end Reverse_List;
procedure Print (L : List) is
begin
for E of L loop
Put_line (Integer'Image (E));
end loop;
end Print;
L : List;
begin
L.Append (1);
L.Append (2);
L.Append (3);
Put_line ("Before:");
Print (L);
--Reverse_List(L);
Reverse_Elements (L);
Put_line ("After:");
Print (L);
end DLL;
Console:
Before:
1
2
3
After:
3
2
1

Related

Iteration through linked list recursively

In this piece of code
Node* insert(int num, Node *head) {
if (head == NULL|| num <= head->next)
return addNewNode(num, head);
head->next = insert(num, head->next);
return head;
}
Why is it
head->next = insert(num,head->next);
and not
head = insert(num,head->next);
I understand we have to traverse through the singly linked list and I thought "head->next" inside the function call takes care of that.
When you don't insert the element as the first node, you want to keep the head and insert into the list's tail.
head->next = insert(num, head->next); replaces the tail with the modified one.
head = insert(num, head->next); would ignore the head and replace it with the result of inserting an element in its tail.
Example: say that we have
head
|
v
1 -> 3 -> X
and want to insert 2.
The recursive insertion returns a pointer to
2 -> 3 -> X
and pointing head->next at this gives
head
|
v
1 -> 2 -> 3 -> X
while your suggestion would give
head
|
v
1 -> 2 -> 3 -> X
and you've lost the 1.

Delete the ith element of a list

Write a function that deletes the ith element of a list. If the length of the list is less than i, return the list.
This is the output wanted:
- deleteIth([1,2,3,4,5,6],3);
val it = [1,2,4,5,6] : int list
- deleteIth([1,2,3,4,5,6],7);
val it = [1,2,3,4,5,6] : int list
Here's my code:
fun deleteIth (L, i) =
let
(* Deletes the element of a list at ith index *)
fun delete (nil, i, position) = nil
| delete (x::xs, i, position) = if i = position then xs else
x :: delete (xs, i, position + 1)
in
if i >= 0 andalso i < length L then delete (L, i, 0) else L
end;
note: the line x :: delete (xs, I, position + 1) should be right after the else in the previous line the line wrap made me show the code this way. Sorry for that.
But my code out puts
- deleteIth([1,2,3,4,5,6],3);
val it = [1,2,3,5,6] : int list
- deleteIth([1,2,3,4,5,6],7);
val it = [1,2,3,4,5,6] : int list
I would appreciate the help thanks.
Since you've got your expected results, here's a shorter version that only traverses the list once, and never beyond the element to remove.
(length must traverse the entire list to determine its length. It's possibly the least useful list function.)
The general case, k > 1 and the list is not empty:
To remove the k:th element, remove element k-1 from the tail of the list, then add the head of the original list to the result.
Base cases:
Removing element 1 from a list produces the tail of the list.
Removing anything from the empty list produces the empty list.
The case where the list is shorter than k will terminate when it reaches the empty list.
Like this:
fun delete_ith ([], k) = []
| delete_ith (x::xs, 1) = xs
| delete_ith (x::xs, k) = x :: delete_ith (xs, k - 1)

Why this code for removing nodes from linked list doesn't work?

I am working on a question on Leetcode, which aims to remove linked list elements.
Here's the question:
Remove Linked List Elements
Example
Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
Return: 1 --> 2 --> 3 --> 4 --> 5
And here's my code:
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* cur = head;
while(cur -> next != NULL && cur -> next -> val != val)
{
cur = cur -> next;
}
cur -> val = cur -> next -> val;
cur -> next = cur -> next -> next;
return head;
}
};
I bumped into a runtime error when I submitted the code. The question is really simple, but since I am not so familiar with C++, I still can't find out where the error is. Could you help me with that?
Your code crashes because the loop has two exit conditions:
You found the node that you were looking for, and
You reached the end of the list without finding the node
Your code assumes it's the first, not second condition, so it dereferences cur->next->val which may lead to a crash.
There are other problems with your code:
You need to handle deletion of multiple items, as shown in the example
You need to prevent memory leaks by freeing deleted nodes
You need to process a situation when head points to the node that must be deleted
You need to process a situation when the list is empty.

Recursive Reverse List

I need to write an algorithm called reverseNodes that takes a RefToNode as a parameter and recuriveley reverses the list the header i came up with was
Algorithm reverse (rList)
reverves elementsin a list
Pre: rList :: a referance to a list to be reversed
Post: elements in rList are reversed
if ( rList !=NULL)
reverseNodes (rList -> head)
return
I need to find a way to write this is psuedocode and find the time complexity
Sometimes it is easier to create some un-formal algorithm gibberish, if you start
with the idea expressed clearly. Then, obfuscate and verbalize until you have something, your professor will happily accept.
So, lets start with our general idea of the algorithm:
let rec fold folder acc l =
match l with
| [] -> acc
| x::xs -> fold folder (folder acc x) xs
let prepend l e = e :: l
let revlist l = fold prepend [] l
...and start to verbalize:
let result = empty list
let l = the list we want to reverse
if l is the empty list, goto 7
let head = l.front, l = l.pop_front()
result.push_front head
goto 3
l = result
The steps 3..6 can be easily expressed as a recursive function:
void loop(list& l, list& result)
{
if( l.is_empty()) return;
auto head = l.front();
l.pop_front();
result.push_front(head);
loop(l,result);
}
As we want to create the illusion of in-place.reversal, our reverse_list function is
void reverse_list( list& l )
{
list result;
loop( l, result);
l = result;
}
Alternate solution
We can also do it in another way:
let rec revlist1 l =
match l with
| [] -> l
| x::xs -> (revlist1 xs) # [x]
This basically states, that the reversed list is the front element of the original list appended to the reverse of the rest.
Translating the algorithm to gibberish form yields:
Node* reverse_list1( Node* list )
{
if( list == NULL) return NULL; // reverse of empty list is empty list.
if( list->next == NULL ) // last element in list?
return list; // the reverse of a list with 1 element is the same.
else
{
Node* head = list;
Node* tail = list->next;
head->next = NULL;
Node* end_of_reverse_tail = tail; // the first will be the last...
Node * result = reverse_list1(tail);
end_of_reverse_tail->next = head;
return result;
}
}
Note, that this is not a tail recursive solution.

How to write iterative inorder traversal for BST in OCaml

It is easy enough to write recursive inorder traversal in OCaml, but how to write iterative one? with for loop or while?
Asking for someone to write something without recursive calls is stupid, but I'll still do it because it's an interesting exercise. Going from recursive to iterative is always the same process.
type tree = Leaf | Node of int * tree * tree
let rec in_order = function
| Leaf -> []
| Node(i,l,r) -> in_order l # (i :: in_order r);;
Alright, now we have our recursive function. The first step is to transform it to tail recursive. This is actually the hardest step since it requires a real logical and algorithmic change.
We are going to add a new parameter to the function that is going to contain the result of the computation :
let rec ino res = function
| Leaf -> ()
| Node(i,l,r) ->
begin
ino res r ;
res := i :: !res ;
ino res l
end
At the end, the result is !res.
Now that we have this, removing the recursive call is very easy, we just have to think about what does the compiler does when he has a recursive call. Well, it just does a while loop, after putting the parameters of the function and the next work to do in a stack. Let's just do it.
open Stack
type work = Value of int | NextNode of tree ref
let ino t : int list =
let res = ref [] in
let stack = Stack.create () in
push (NextNode (ref t)) stack;
try
while true do
let current = pop stack in
match current with
Value i -> res := i :: !res
| NextNode n ->
begin
match !n with
Leaf -> ()
| Node(i,l,r) ->
begin
push (NextNode (ref l)) stack;
push (Value i) stack;
push (NextNode (ref r)) stack
end
end
done;
assert false
with
| Empty -> !res
Here we just remember the next thing to do. We know that when we reach a node we have to treat its right child, then the value of the node, then its left child, so we just put all this in the stack (in reverse order of course), and we keep going to the next element of the stack. When the stack is empty, we have visited the whole tree, and we can return.
I hope that this post manages to convince some people of the power of recursion over iterative programming. 3 lines Vs 26 lines. QED.
Here's another take on iterative in-order traversals:
type 'a node = {mutable data: 'a;
mutable left : 'a node option;
mutable right: 'a node option; }
let new_node data = {data; left = None; right = None;}
let insert tree new_data =
let module Wrapper = struct exception Stop_loop end in
let iter = ref tree in
try
while true do
if new_data < !iter.data
then match !iter.left with
| None ->
!iter.left <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some left_tree -> iter := left_tree
else if new_data > !iter.data
then match !iter.right with
| None ->
!iter.right <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some right_tree -> iter := right_tree
done
with Wrapper.Stop_loop -> ()
let in_order_traversal tree =
let module W = struct exception Stop_loop end in
let visited_stack = Stack.create () in
let iter_node = ref (Some tree) in
try while true do
(* Inner loop, we keep trying to go left *)
(try while true do
match !iter_node with
| None -> raise W.Stop_loop
| Some left ->
Stack.push left visited_stack;
iter_node := left.left
done;
with W.Stop_loop -> ());
(* If we have no more to process in the stack, then we're
done *)
if Stack.length visited_stack = 0
then raise W.Stop_loop
else
(* Here we're forced to start moving rightward *)
let temp = Stack.pop visited_stack in
Printf.sprintf "%s " temp.data |> print_string;
iter_node := temp.right
done
with W.Stop_loop -> ()
let () =
let root = new_node "F" in
["B";"G";"A";"D";"I";"C";"E";"H"] |> List.iter (insert root);
in_order_traversal root;
print_newline ();