BST to Linked list - linked-list

Can anyone suggest an algorithm to convert a Binary Search Tree to a singly linked list.
Also note that at each step of conversion the highest values node in the list should point to the smallest valued node in the list.

if(!tree.isEmpty())
{
Node node1 = tree.removeMin();
Node node2;
Node currentNode;
Node temp;
if(!tree.isEmpty())
{
node2 = tree.removeMax();
node2.setNext(node1);
currentNode = node2;
while(!tree.isEmpty())
{
temp = tree.removeMin();
temp.setNext(currentNode);
currentNode = temp;
}
}
Node head = temp;
}
This conforms to a singly linked list and the maximum value in the list always points to the least value in the list. No other qualifications were given.

public static LinkedListNode<Integer> constructLinkedList(BinaryTreeNode<Integer> root) {
if(root == null)
return null;
LinkedListNode<Integer> newHead = constructLinkedList(root.left);
LinkedListNode<Integer> temp = newHead;
if(newHead == null)
newHead = new LinkedListNode<>(root.data);
else
{
while(temp != null && temp.next != null)
{
temp = temp.next;
}
temp.next = new LinkedListNode<>(root.data);
}
LinkedListNode<Integer> rightHead = constructLinkedList(root.right);
if(newHead.next == null)
newHead.next = rightHead;
else
temp.next.next = rightHead;
return newHead;
}

Related

Reverse K group node in linked list

**The question is that input linked list as
1->2->3->4->5->6->7->8->9->10->11->12
And the output should be the list should be reversed with group of 3
3->2->1->4->5->6->9->8->7->10->11->12**
I tried this method but this revese the whole list
// Node *previousNode = NULL;
// Node *currentNode = head;
// Node *nextNode;
// while (currentNode!=NULL){
// nextNode = currentNode->nextNodeAddress;
// currentNode->nextNodeAddress = previousNode;
// previousNode = currentNode;
// currentNode = nextNode;
// }
// head = previousNode;

How would you prevent a user from inputting a duplicate value in a linked list?

I've been trying to figure out how to prevent a user from entering a duplicate value and honestly I am struggling so much for an answer that's probably really simple once I see it, but I can't. The function is below along with the struct node. I would really appreciate it if someone could help me out here.
struct node {
int data = -1;
node * current;
node * next;
};
node * start = NULL;
```
void addNode(struct node & n) {
if (n.data == -1) {
cout << "List not created yet." << endl;
} else {
node * temp;
node * temp2;
temp = new node;
cout << "What number would you like to enter:" << endl;
cin >> temp -> data;
cout << endl;
int value;
value = temp -> data;
temp = start;
while (temp != NULL) {
if (temp -> data == value) {
cout << "Duplicate Number!" << endl;
} else {
temp = temp -> next;
}
temp = temp -> next;
}
if (start == NULL) {
start = temp;
} else {
temp2 = start;
while (temp2 -> next != NULL) {
temp2 = temp2 -> next;
}
temp2 -> next = temp;
}
}
}
Here are some remarks on your code:
Don't make start a global variable. Instead make it local to main and pass it as argument to the addNode function
Use nullptr instead of NULL
Don't ask for the user's input inside the addNode function. By the principle of separation of concern, keep the I/O aspects outside that function.
Instead pass the value as argument to addNode
You should treat a node differently when it has the value -1. An empty list is not a list with one node that has the value -1. An empty list is a null pointer.
Even if a list is empty, it should be possible to add the first node with this function
Use more descriptive variable names. n for a node instance is not very clear. Also temp and temp2 are not very clear. One of the two is the newly created node, so it could be named newNode.
After you have created the new node, and assigned its reference to temp, you assign a new value to temp with temp = start, and so you've lost (and leaked) the newly created node.
In your loop, you'll execute temp = temp->next twice when the value does not match. This should of course only be done once per iteration.
Even when your code finds a duplicate and outputs a message, it still continues the process. Instead you should stop the process, and not create the node (or if you already did: dispose it with delete).
It is a pity that you need to traverse the list again from the start to find the last node and append the new node there. You should be able to do that in the first loop where you look for the duplicate.
Here is a correction:
bool addNode(node* &start, int value) {
node * current = start;
if (start != nullptr) {
while (current->data != value && current->next != nullptr) {
current = current->next;
}
if (current->data == value) {
return false; // duplicate!
}
}
node* newNode = new node;
newNode->data = value;
if (start != nullptr) {
current->next = newNode;
} else {
start = newNode;
}
return true;
}
Note that this function returns a boolean: if true then the node was inserted. The other case means there was a duplicate.
Your main function could look like this:
int main() {
// define start as local variable
node * start = nullptr; // Use nullptr instead of NULL
while (true) {
int value;
// Don't do I/O together with list-logic
cout << "What number would you like to enter:" << endl;
cin >> value;
cout << endl;
if (value == -1) break;
if (!addNode(start, value)) {
cout << "Duplicate Number!" << endl;
}
}
}

Merge Sort for Singly Linked List seems to remove any numbers larger than the final number I input into the list

I am currently trying to formulate a mergeSort mechanism for a singly linked list. Through research and finding consistent ideas about A) a merge sort being the best way to sort a singly linked list, and B) that these are the key components for performing such an operation, I have arrived at this following code. It almost works exactly as intended, but will only return all of the integers larger than the last inputted number. For example, inputting 7, 6, 5, 4, 3, 2, 1 will return 1, 2, 3, 4, 5, 6, 7, but inputting 1, 2, 3, 4, 5 will only return 5. I've used random input orders so it's not a problem localised to just inputting the numbers in reverse order, but literally any order. If a number is smaller than the final number, it gets removed from the list in the sort process. I cannot locate the cause for this at all. My original problem was caused by an errant while loop that was stopping the iterations after one go, so once I removed that the merge sort was working, but for this problem I have just described.
Any and all advice or suggestions are more than welcome, and thanks for any input you have. My knowledge of linked lists and recursion isn't the greatest, so I really welcome all input/constructive criticism here.
public Node mergeSort(Node head) {
if (head == null || head.getNext() == null) return head;
Node midpoint = findMidpoint(head);
Node rightliststart = midpoint.getNext();
midpoint.setNext(null);
Node rightlist = mergeSort(rightliststart);
Node sorted = sort(leftlist, rightlist);
return sorted;
}
public Node findMidpoint(Node head) {
if (head == null) return head;
Node slowpointer = head;
Node fastpointer = slowpointer.getNext();
while (fastpointer != null) {
fastpointer = fastpointer.getNext();
if (fastpointer != null) {
slowpointer = slowpointer.getNext();
fastpointer = fastpointer.getNext();
}
}
return slowpointer;
}
public Node sort(Node one, Node two) {
Node temp = null;
if (one == null) return two;
if (two == null) return one;
if (one.getData() <= two.getData()) {
temp = one;
temp.setNext(sort(one.getNext(), two));
} else {
temp = two;
temp.setNext(sort(one, two.getNext()));
}
return temp;
}
Example merge code. This shows how the dummy node is used to simplify the code (avoids special case to update head on first node merged).
// merge two already sorted lists
static Node merge(Node list0, Node list1) {
if(list0 == null)
return list1;
if(list1 == null)
return list0;
Node temp = new Node(); // dummy node
Node dest = temp;
while(true){
if(list0.data <= list1.data){
dest.next = list0;
dest = list0;
list0 = list0.next;
if(list0 == null){
dest.next = list1;
break;
}
} else {
dest.next = list1;
dest = list1;
list1 = list1.next;
if(list1 == null){
dest.next = list0;
break;
}
}
}
return temp.next;
}
Example top down merge sort code. It scans the list one time to get the size of the list to avoid double scanning (fast, slow), only scanning n/2 nodes for each recursive split.
// return size of list
static int size(Node head) {
int i = 0;
while(head != null){
head = head.next;
i++;
}
return i;
}
// advance to node n
static Node advance(Node head, int n) {
while(0 < n--)
head = head.next;
return head;
}
// top down merge sort for single link list entry function
static Node sorttd(Node head) {
int n = size(head);
if(n < 2)
return head;
head = sorttdr(head, n);
return head;
}
// top down merge sort for single link list recursive function
static Node sorttdr(Node head, int n) {
if(n < 2)
return head;
int n2 = (n/2);
Node node = advance(head, n2-1);
Node next = node.next;
node.next = null;
head = sorttdr(head, n2);
next = sorttdr(next, n-n2);
head = merge(head, next);
return head;
}
Example bottom up merge sort code. It uses a small (32) array of lists, where array[i] is a list with 0 (empty slot) or 2^i nodes. array[{0 1 2 3 4 ...}] = sorted sub-lists with 0 or {1 2 4 8 16 ...} nodes. Nodes are merged into the array one at a time. A working list is created via a sequence of merge steps with a caller's list node and the leading non-empty slots in the array. The size of the working list doubles with each merge step. After each non-empty slot is used to merge into the working list, that slot is set to empty. After each sequence of merge steps is done, the first empty slot after the leading non-empty slots is set to the working list. A prior slots will now be empty. Once all nodes are merged into the array, the array is merged into a single sorted list. On a large list that doesn't fit in cache, and with randomly scattered nodes, there will be a lot of cache misses for each node accessed, in which case bottom up merge sort is about 30% faster than top down.
// bottom up merge sort for single link list
static Node sortbu(Node head) {
final int NUMLIST = 32;
Node[] alist = new Node[NUMLIST];
Node node;
Node next;
int i;
// if < 2 nodes, return
if(head == null || head.next == null)
return null;
node = head;
// merge node into array
while(node != null){
next = node.next;
node.next = null;
for(i = 0; (i < NUMLIST) && (alist[i] != null); i++){
node = merge(alist[i], node);
alist[i] = null;
}
if(i == NUMLIST) // don't go past end of array
i--;
alist[i] = node;
node = next;
}
// node == null
// merge array into single list
for(i = 0; i < NUMLIST; i++)
node = merge(alist[i], node);
return node;
}

Removing a range of values from a linked list

I am trying to remove a node from a linked list if its value falls within a certain range (greater than or equal to low and less than or equal to high). This code only removes the first value found within the range.
public void removeData(E low, E high) {
Node previousNode = root;
Node deleteNode = previousNode.getNext();
while (deleteNode != null) {
if (deleteNode.getValue().compareTo(low) >= 0 && deleteNode.getValue().compareTo(high) <= 0) {
previousNode.setNext(deleteNode.getNext());
}
previousNode = previousNode.getNext();
deleteNode = deleteNode.getNext();
}
}
In this code what you need to do is:
public void removeData(E low, E high) {
Node previousNode = root;
Node deleteNode = previousNode.getNext();
while (deleteNode != null) {
if (deleteNode.getValue().compareTo(low) >= 0 && deleteNode.getValue().compareTo(high) <= 0) {
previousNode.setNext(deleteNode.getNext());
}else{
previousNode = previousNode.getNext();
}
deleteNode = deleteNode.getNext();
}
}
because if one node is deleted the previous node doesn't need to incremented just deleteNode has to. and check for another deleteNode.
Hope this may help you.
Thanks!!

Sorted Insert in linked list

Given a problem to insert a new node within a sorted linked list in the correct position, I have come up with the following solution.
void SortedInsert(node** headref, node* newnode) {
node* prev = NULL;
node* curr = *headref;
for (; curr; ) {
if (curr->info > newnode->info) {
break;
}
prev = curr;
curr = curr->next;
}
if (!prev) {
newnode->next = *headref;
*headref = newnode;
} else {
newnode->next = prev->next;
prev->next = newnode;
}
}
Does this work.
Are there any edge cases this does not work for. Is there a simpler solution.
Instead of making curr point to the node before which you want to insert, make curr point to the pointer that points to the node before which you want to insert.

Resources