What is the best way to flatten a linked list with lists as values?

I think your method is good but I also would suggest the following:

Cases[acc, {x_?NumberQ, y_?NumberQ} :> {x, y}, -1]

or easier:

Cases[acc, {__}, {-2}]                (*@ Alexey Popkov*)

This would be better but if you don't have empty list at the end.

Level[acc, {-2}]

(*{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {}}*)

in this case you may delete the empty list using any method. for example :

Most@Level[acc, {-2}]

(*{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}}*)

A different head

You can avoid the problem from the outset by using a different head for your linked "list" e.g. AngleBracket:

flatAcc = {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}}

x = Fold[〈#2, #〉 &, 〈〉, Reverse @ flatAcc]
〈{1,2}, 〈{2,3}, 〈{3,4}, 〈{4,5}, 〈{5,6}, 〈〉〉〉〉〉〉

Now Flatten can be used:

Flatten[x, ∞, AngleBracket]
〈{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}〉
  • You can Apply List as needed at this point.

  • There is nothing special about AngleBracket; I just used it because it looks rather nice.

Bag functionality

One may use the undocumented Internal`Bag functionality in place of linked lists in many applications.

bag = Internal`Bag[];                          (* create bag *)

Scan[Internal`StuffBag[bag, #] &, flatAcc];    (* incrementally fill bag *)

Internal`BagPart[bag, All]                     (* get flat bag contents *)
{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}}

Performance

m_goldberg asserted that a Flatten and Partition is the fastest method available. This is not borne out in my testing.

I could not include Algohi's Level method as Mathematica 10.0.1 crashed when the linked list grew longer.

(* timing function *)
SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]

(* random pairs common to all tests *)
rand = RandomInteger[99, {2000000, 2}];

(* build each "linked list" or equivalent *)
linked = Fold[List, rand];
linked2 = Fold[AngleBracket, rand];
bag = Internal`Bag[rand];

(* timings *)
Flatten[linked] ~Partition~ 2      // timeAvg
Flatten[linked2, ∞, AngleBracket]  // timeAvg
Internal`BagPart[bag, All]         // timeAvg
1.529

0.131

0.0187

We see that in this test using AngleBracket and Flatten alone is more than an order of magnitude faster than using Flatten and Partition, and the Bag method is nearly two orders of magnitude faster than the original.

Notes:

  • Lest it confuse anyone the two-argument from of Fold is used; see: Shorter syntax for Fold and FoldList?

  • The linked list format used is different as I used e.g. bare List rather than {#2, #} & but I tried both ways and the timings were unaffected.


Addendum

Algohi wrote that I should provide a method to convert the OP's acc format to another head. I agree.

rule = {a_, b_} :> 〈a, b /. rule〉;

acc /. rule
〈{1,2}, 〈{2,3}, 〈{3,4}, 〈{4,5}, 〈{5,6}, {}〉〉〉〉〉

This misses {} but that can be dropped later with Most. A more general replacement function:

convert[_[a_, b_], h_] := h[a, convert[b, h]]
convert[_[], h_] := h[]

Now:

convert[〈{1,2}, 〈{2,3}, 〈{3,4}, 〈{4,5}, 〈{5,6}, {}〉〉〉〉〉, foo]
foo[{1, 2}, foo[{2, 3}, foo[{3, 4}, foo[{4, 5}, foo[{5, 6}, foo[]]]]]]

It would of course be more efficient to construct the linked "list" in this format to begin with.


A generalization

acc = {{a, b, c}, {{2}, {{"a", 4}, {{4, 5}, {{5, 6}, {}}}}}};

Cases[acc, {x__?AtomQ} :> {x}, -1]

{{a, b, c}, {2}, {"a", 4}, {4, 5}, {5, 6}}