g | x | w | all
Bytes Lang Time Link
149JavaScript V8241211T194004ZWeird Gl
213JavaScript V8241210T073023Zthejonym
126Perl 5 MListUtil=max a241210T210400ZXcali
258Setanta241210T081311Zbb94
041Canvas210207T113354ZRazetime
167PowerShell200228T103527Zmazzy
318C#151217T123440ZHand-E-F
153Ruby151208T172258Zmanatwor
231PHP151207T225519Zinsertus
048Pyth151207T200005ZJakube
165Python 2151207T060316Zxsot

JavaScript (V8), 157 156 154 153 149 bytes

f=(l,i=Math.max(...m=l.map(Math.abs)))=>m.map((j,J)=>~i?i<j?l[J]<0?" /|\\":" / \\":!j|i>j?"    ":"  ^ ":j?"__|_":"____").join``+(~i?`
`+f(l,i-1):"_")

Try it online!

-1 byte thanks to emanresu A

Hello! First time posting here, I wanted to try to solve this problem as my first challenge, I saw that thejonymyster also answered it, but I was pretty happy with the answer I found, so I hope that I'm following the rules in this situation. Anyway, here's a prettier version of the code, mostly using a lot of ternaries and some recursion:

/* Line  1   ^   i: index of the line from the maximum absolute value to -1
   Line  0  / \  j: absolute value of each element
   Line -1  _|_  l[J]: non-absolute value (retrieved using the index) */

f=(l, i=Math.max(...m=l.map(Math.abs))) =>
    m.map((j, J) =>
        ~i ? i<j ?
            l[J]<0 ? " /|\\" : " / \\" :
        !j | i>j ?
            "    " : "  ^ "
        : j ? "__|_" : "____"
    ).join``+(~i ? `
`+f(l,i-1) : "_") // empty line

JavaScript (V8), 213 bytes

x=>{a=Math;b=a.abs;c=a.sign;e=x.map(b);d=a.max(...e)+1;f="";while(d--){e.map((g,h)=>f+=["    ",`  ${c(g)?"^":" "} `,` /${1+c(x[h])?" ":"|"}\\`][1+c(g-d)]);f+="\n"}return f+`_${x.map(i=>i?"_|_":"___").join("_")}_`}

Try it online!

Seems like the same as the other non-transposing answers, not all too many strategies to solve this. Transposing is probably shorter in js but I like this method better.

Perl 5 -MList::Util=max -a, 126 bytes

//&say map"  ^ "x($_&&$'==-abs)||($_<0?' /|\\':' / \\')x($'>-abs)||$"x4,@F for-(max map{abs}@F)..0;say'_',map$_?"_|__":____,@F

Try it online!

Setanta, 258 bytes

gniomh(l){s:=""h:=0f:=fad@l D:=dearbh@mata le i idir(0,f)h=uas(h,D(l[i]))ma h{le j idir(h,-1){s+=" "le i idir(0,f)s+=["   "," ^ ",["/ \\","/|\\"][l[i]<0|0&1]][l[i]&uas(0,ios(2,1+D(l[i])-j))]s+="\n"}}s+="_"le i idir(0,f)s+=["___","_|_"][l[i]|0&1]toradh s+"_"}

try-setanta.ie link

Canvas, 41 bytes

H?¹⤢\ /*¹0<? /∙|/╋} v∔↕_|__¶∔↕]_4×}+}_;+↕

Try it here!

PowerShell, 167 bytes

$h=(($r=($args|%{$a,$x=$_,-$_-ge0
'_';'_'+'/'*$a;'|_'[!$_]+(' ','|')[$_-lt0]*$a+'^'*!!$_
'_'+'\'*$a})+'_')|% Le*|sort)[-1]
$z=$r|% *ht $h;--$h..0|%{-join($z|% Ch* $_)}

Try it online!

Explanation:

  1. Draw a rotated forest line by line

    Rotated forest

  2. Pad right and

  3. Rotate -90.

Unrolled:

# a rotated forest with underscore after the last tree
$rotatedForest=$args|%{
    $abs,$x=$_,-$_-ge0
    '_'
    '_'+'/'*$abs
    '|_'[!$_]+(' ','|')[$_-lt0]*$abs+'^'*!!$_
    '_'+'\'*$abs
}
$rotatedForest += '_'

# calc height
$height = ($rotatedForest|% Length|sort)[-1]

# PadRight all trees
$z = $rotatedForest|% PadRight $height

# Rotate -90
--$height..0|%{
    -join($z|% Chars $_)
}

C#, 318 bytes

I tried transposing the array. I'm not sure if that was the best solution.

string F(int[]a){int i=a.Length,j,w=i*4+1,h=0;string f="",o=f;for(;i-->0;){j=a[i];f+=","+" _,".PadLeft(j=j>0?j+3:-j+3,'\\')+(j>3?"^"+"|_,".PadLeft(j,a[i]<0?'|':' '):"_,")+" _,_".PadLeft(j+1,'/');h=h<j?j:h;}f="_".PadLeft(h=h>3?h:2,'\n')+f;for(i+=h<3?1:0;++i<h;)for(j=w;j-->0;)o+=f.Split(',')[j].PadLeft(h)[i];return o;}

Indentation and newlines for clarity:

string F(int[]a)
{
    int i=a.Length,
        j,
        w=i*4+1,
        h=0;
    string f="",o=f;
    for(;i-->0;){
        j=a[i];
        f+=","+" _,".PadLeft(j=j>0?j+3:-j+3,'\\')+(j>3?"^"+"|_,".PadLeft(j,a[i]<0?'|':' '):"_,")+" _,_".PadLeft(j+1,'/');
        h=h<j?j:h;
    }
    f="_".PadLeft(h=h>3?h:2,'\n')+f;
    for(i+=h<3?1:0;++i<h;)
        for(j=w;j-->0;)
            o+=f.Split(',')[j].PadLeft(h)[i];
    return o;
}

Ruby, 157 156 153 characters

->h{r=[]
h.map{|i|j=i.abs
r+=[s=?_,?/*j+s,i==0?s:?^+(i>0?' ':?|)*j+?|,?\\*j+s].map{|l|l.rjust(h.map(&:abs).max+2).chars}}
r.transpose.map{|l|l*''}*$/+?_}

Written just because initially Array.transpose looked like a good idea. Not anymore.

Sample run:

2.1.5 :001 > puts ->h{r=[];h.map{|i|j=i.abs;r+=[s=?_,?/*j+s,i==0?s:?^+(i>0?' ':?|)*j+?|,?\\*j+s].map{|l|l.rjust(h.map(&:abs).max+2).chars}};r.transpose.map{|l|l*''}*$/+?_}[[4, 0, -1, -6, 2]]
              ^     
             /|\    
  ^          /|\    
 / \         /|\    
 / \         /|\  ^ 
 / \      ^  /|\ / \
 / \     /|\ /|\ / \
__|_______|___|___|__

PHP, 231 277 bytes

This challenge has a beautiful output.

$x=fgetcsv(STDIN);for(;$i<2+max(array_map(abs,$x));$i++)for($j=0;$j<count($x);){$_=$x[$j++];$o[$i].=!$i?$_?'__|_':____:(abs($_)>=$i?0>$_?' /|\\':' / \\':($i-1&&abs($_)==$i-1?'  ^ ':'    '));}echo implode("
",array_reverse($o))."_";

Reads a comma separated list (whitespaces are optional) from STDIN:

$ php trees.php
> 1, 2, 0, -4, 6

Ungolfed

$x=fgetcsv(STDIN);
for(;$i<2+max(array_map(abs,$x));$i++)
    for($j=0;$j<count($x);){
        $_=$x[$j++];
        $o[$i] .= !$i ? $_?'__|_':____
                      : (abs($_)>=$i ? 0>$_?' /|\\':' / \\'
                                     : ($i-1&&abs($_)==$i-1 ? '  ^ ' : '    '));
    }
echo implode("\n",array_reverse($o))."_";

Edits

Pyth, 48 bytes

j_.t+sm.i,J\_?d++\|sm?>d0\ \|d\^Jms+Jmkd"/\\"QJd

Try it online: Demonstration or Test Suite

Too lazy for a full explanation. Here just short overview:

I generate the columns first. So the image:

      ^ 
  ^  /|\
 / \ /|\
__|___|__

gets generated as:

["_", "_/", "| ^", "_\", "_", "_//", "|||^", "_\\", "_"]

Notice, that I'm generating only the lower part (everything without the spaces). And I'm also generating them from bottom to top. This is done pretty straightforward.

Then I can use the .t method to append spaces to the strings, so that each string has an equal length. And afterwards I reverse the order and print.

Python 2, 165 bytes

a=input()
l=max(map(abs,a))
while l+2:s=' _'[l<0];print(s+s.join((([' ^ ','//| \\\\'[x>0::2],'   '][cmp(abs(x),l)],'_|_')[l<0],s*3)[x==0]for x in a)+s).rstrip();l-=1

This is a full program that accepts a list as input. I'm still golfing this horrid mess.