I have two classes:
public class List {
public Node _head;
}
And:
public class Node {
public String _word;
public Node _next;
}
I have a constructor in "List", which gets a String as a parameter and puts every word in a seperate Node, like this:
public List(String text) {
if (text.length() == 0)
_head = null;
createList(text);
}
private void createList(String text) {
int lastIndex=0;
String temp;
for (int i=0;i<text.length();i++) {
if (text.charAt(i)==' '|| i==text.length()-1) {
if (i == 0) { // Space in the begining
lastIndex=1;
continue;
}
if (i == text.length()-1) { // If we reached to the last char of the string
if (text.charAt(i) == ' ') { // If it's a space, don't include it
temp = text.substring(lastIndex,i);
} else {
temp = text.substring(lastIndex,i+1);
}
} else {
temp = text.substring(lastIndex,i);
}
addToBegining(temp);
lastIndex=i+1;
}
}
}
Anyway, when I'm trying to use a mergesort on the linked list, I can't manage to get it working.
This is the sorting code:
public Node merge_sort(Node h) {
if (h == null || h._next == null) { return h; }
Node middle = getMiddle(h); //get the middle of the list
Node sHalf = middle._next; middle._next = null; //split the list into two halfs
return merge(merge_sort(h), merge_sort(sHalf)); //recurse on that
}
public Node merge(Node a, Node b) {
Node dummyHead, curr;
dummyHead = new Node();
curr = dummyHead;
while (a !=null && b!= null) {
if (a._word.compareTo(b._word) <= 0) {
curr._next = a;
a = a._next;
} else {
curr._next = b;
b = b._next;
}
curr = curr._next;
}
curr._next = (a == null) ? b : a;
return dummyHead._next;
}
public Node getMiddle(Node h) {
if (h == null) { return h; }
Node slow, fast;
slow = fast = h;
while (fast._next != null && fast._next._next != null) {
slow = slow._next;
fast = fast._next._next;
}
return slow;
}
Any idea what's wrong? I'm trying to make a new TextList with the String "Hello New World A Dawn Is There" and Output is: "There World"..
Please change as below. I think you forgot to assign the curr
node to the appropriate values after the if-else
.
public Node merge(Node a, Node b)
{
Node dummyHead, curr;
dummyHead = new Node();
curr = dummyHead;
while (a != null && b != null)
{
if (a._word.compareTo(b._word) <= 0)
{
curr._next = a;
curr = a;
a = a._next;
}
else
{
curr._next = b;
curr = b;
b = b._next;
}
curr = curr._next;
}
curr._next = (a == null) ? b : a;
return dummyHead._next;
}
Merge sort is not suitable for Linked List as you need acces to middle element of your list (you divide list into 2 sublists). With linked list you have access only to first element of the list (singly-linked list).
It is not feasible to try to use it, as you have to first find a link to middle element every time you divide your list. Better try insertion sort or quick-sort with 1st element of linked list as a pivot.
EDIT: Yesterday, I replied from my phone and had no way to analyse your code.
Today I tested your code.
I create input list with words "ant", "lion", "pig", "rat", "bat", "tiger", "cat", "dog"
and use merge_sort()
method. Output of it was nicely sorted list.
The only alternations to your code I did, was adding constructors to Node()
class
Node () {
_word = "";
_next = null;
}
Node (String word) {
_word = word;
}
but that was only for me to make it easier create new node.
Can you show how do you test your output list?
EDIT2: I didn't checked your code to separate words from string as you stated it works)
EDIT3: Your merge method have also other problems but this one is the main one.
Think how your merge()
method is working when you try to merge 2 list: a = { "ant", "bat", "dog"} b = { "cat", "lion", "rat"}
while loop iterations:
curr = {"ant"} a = { "bat", "dog" } b = { "cat", "lion", "rat"}
curr = {"ant", "bat"} a = { "dog" } b = { "cat", "lion", "rat"}
curr = {"ant" "bat", "cat"} a = { "dog"} b = { "lion", "rat" }
curr = {"ant", "bat", "cat", "dog"} a = { } b = { "lion", "rat" }
a == null, while loop terminated
what happened next? Your method assign only one time next element from list b and exit. Loosing 2nd element ("rat") from b.
I changed your code slightly, getMiddle()
method is same as yours:
public Node mergeSort(Node h) {
if (h._next != null) { // check for recursion if in list left at least 2 elements
Node middle = getMiddle(h);
Node sHalf = middle._next; middle._next = null;
return merge(mergeSort(h), mergeSort(sHalf));
}
else { // if only 1 element then no need to sort
return h;
}
}
public Node merge(Node a, Node b) {
Node dummyHead = new Node();
Node curr = dummyHead;
while (a !=null && b!= null) {
if (a._word.compareTo(b._word) <= 0) {
curr._next= a;
a = a._next;
} else {
curr._next = b;
b = b._next;
}
curr = curr._next;
}
// if list a still has some elements, insert them to the end of the curr
while(a != null) {
curr._next = a;
a = a._next;
curr = curr._next;
}
// if list b still has some elements, insert them to the end of the curr
while(b != null) {
curr._next = b;
b = b._next;
curr = curr._next;
}
return dummyHead._next;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.