2

Thanks for looking at this question in advance.

I am trying to order the following list of items:

Bpgvjdfj,Bvfbyfzc
Zjmvxouu,Fsmotsaa
Xocbwmnd,Fcdlnmhb
Fsmotsaa,Zexyegma
Bvfbyfzc,Qkignteu
Uysmwjdb,Wzujllbk
Fwhbryyz,Byoifnrp
Klqljfrk,Bpgvjdfj
Qkignteu,Wgqtalnh
Wgqtalnh,Coyuhnbx
Sgtgyldw,Fwhbryyz
Coyuhnbx,Zjmvxouu
Zvjxfwkx,Sgtgyldw
Czeagvnj,Uysmwjdb
Oljgjisa,Dffkuztu
Zexyegma,Zvjxfwkx
Fcdlnmhb,Klqljfrk
Wzujllbk,Oljgjisa
Byoifnrp,Czeagvnj

Into the following order:

Bpgvjdfj
Bvfbyfzc
Qkignteu
Wgqtalnh
Coyuhnbx
Zjmvxouu
Fsmotsaa
Zexyegma
Zvjxfwkx
Sgtgyldw
Fwhbryyz
Byoifnrp
Czeagvnj
Uysmwjdb
Wzujllbk
Oljgjisa
Dffkuztu

This is done by:

  1. Taking the first pair and putting the names into a list
  2. Using the second name of the pair, find the pair where it is used as the first name
  3. Add the second name of that pair to the list
  4. Repeat 2 & 3

I am populating an unordered_map with the pairs then sorting and adding each name to a list. This can be seen in the following code:

westIter = westMap.begin();
std::string westCurrent = westIter->second;
westList.push_front(westCurrent);

for(int i = 0; i < 30; i++)
{
    if(westMap.find(westCurrent) != westMap.end())
    {
        //find pair in map where first iterator is equal to "westCurrent"
        //append second iterator of pair to list
    }
    westIter++;
}

Note: I'm not sure if "push_front" is correct at this moment in time as I have only got the first value inserted.

My question is could someone give me some insight as to how I could go about this? As I am unsure of the best way and whether my thinking is correct. Any insight would be appreciated.

wilcode
  • 633
  • 2
  • 10
  • 25
  • Three million men with distinct names were laid end-to-end, reaching from New York to California. Each participant was given a slip of paper on which he wrote down his own name and the name of the person immediately west of him in the line. The man at the extreme western end of the line didn’t understand what to do, so he threw his paper away; the remaining 2,999,999 slips of paper were put in a huge basket and taken to the National Archives in Washington, D.C. Here the contents of the basket were shuffled completely and transferred to magnetic tapes. The unordered_map is shuffling the pairs. – wilcode Jan 29 '13 at 01:54
  • Are you trying to sort an `unordered_map`??? – Karthik T Jan 29 '13 at 01:55
  • @KarthikT The names are inserted from a file into an unordered_map to shuffle them and then organised into a list. – wilcode Jan 29 '13 at 01:57
  • 1
    Do you need to regenerate the order of the 2,999,999 names? Sorting is a bad name for it but I think I understand – Karthik T Jan 29 '13 at 02:01
  • @KarthikT Yes, another section of my code does the opposite of this. – wilcode Jan 29 '13 at 02:03
  • 1
    Regarding the tags: Why 'knuth'? – jogojapan Jan 29 '13 at 02:03
  • @jogojapan It's in reference to his description that the problem of sorting when the ordering of keys is not obvious. The comment I posted above is the reproduction of it. – wilcode Jan 29 '13 at 02:07
  • Oh. Donald Knuth described this problem. Hmm. I think I'd rather put the quote and his name in the question itself instead of using the tag. Not sure what that tag is supposed to be used for anyway (the Knuth algorithm perhaps?) – jogojapan Jan 29 '13 at 02:11
  • 1
    IMO, thinking of this as sorting is a mistake. What you really have is a "relational linked list" -- i.e., a linked list, but instead of each node containing a pointer to the next node, the pointer field contains the value of the next node. Alternatively, you could think of it as (sort of) a topological sort. – Jerry Coffin Jan 29 '13 at 02:13

2 Answers2

2

There is but one weakness in your plan. You need to first find the first person of the chain, the Mr New York.

Your algorithm assumes the line starts with the first guy. For that to work, you should first scan the entire map to find the one name that does not appear as a second element. That is Mr New York and you can proceed from there. push_back is what you would need to use here.

Karthik T
  • 31,456
  • 5
  • 68
  • 87
  • Edited the comment now, but yes I did it the wrong way round! Well that has shed some light on the situation.. – wilcode Jan 29 '13 at 02:14
  • 1
    Yup thats the one. So one scan to find the first, and a second to generate the list – Karthik T Jan 29 '13 at 02:14
  • Are you saying that "Xocbwmnd" should be the first, then from his second name, search from there. So that is why my sorted list came out shorter than it should have.. – wilcode Jan 29 '13 at 02:16
  • @lauw0203 yup, exactly what I mean. – Karthik T Jan 29 '13 at 02:25
  • I've just spoken to someone else who is doing this too and they have said that because you are going east and west, all the values will be accumulated into the list, so you can start from the beginning. – wilcode Jan 29 '13 at 02:35
  • @lauw0203 beginning of the map? I dont see how that would work unless you 1) make multiple passes, 2) stitch multiple lists together or 3) go backwards.. – Karthik T Jan 29 '13 at 02:39
  • You go through the westerly map and add to the list and then the easterly map and add the missing values apparently.. – wilcode Jan 29 '13 at 02:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23539/discussion-between-karthik-t-and-lauw0203) – Karthik T Jan 29 '13 at 02:47
1
  1. Create a data structure that stores a chain, its front and back. Store in a hash table with 'back' as key.
  2. Create a bunch of singleton chains (one for each element)
  3. Iteratively, pick a chain find its 'front' in the hash table (i.e. find another chain that has the same element as 'back') and merge them
  4. Do it until you are left with only one chain
ElKamina
  • 7,747
  • 28
  • 43