La réponse à cette question dépend exactement ce que vous voulez apprendre.
Python et Ruby
De haut niveau des langages comme Python et Ruby sont souvent proposés car ils sont de haut niveau et la syntaxe est tout à fait lisible. Cependant, ces langues ont tous des abstractions pour le commun des structures de données. Il n'y a rien qui vous empêche de mise en œuvre de vos propres versions de l'apprentissage de l'exercice, mais vous pouvez trouver que vous êtes en train de construire de haut niveau des structures de données au-dessus des autres niveau élevé de structures de données, ce qui n'est pas forcément utile.
Aussi, Ruby et Python sont typées dynamiquement langues. Cela peut être bon, mais il peut aussi être source de confusion pour les débutants et il peut être plus difficile (à l'origine) pour attraper des erreurs, car en général, ils ne se manifeste qu'à l'exécution.
C
C est à l'autre extrême. Il est bon si vous voulez vraiment apprendre des détails de bas niveau, comme la façon dont la mémoire est gérée, mais la gestion de la mémoire est tout à coup une considération importante, comme dans l'utilisation correcte de la fonction malloc()/free(). Qui peut être une source de distraction. Aussi, C n'est pas orienté objet. Ce n'est pas une mauvaise chose, mais simplement de noter.
C++
C++ a été mentionné. Comme je l'ai dit dans le commentaire, je pense que c'est un terrible choix. C++ est affreusement compliqué, même en simple d'utilisation et a un montant ridicule de "pièges". Aussi, le C++ n'a pas de classe de base commune. Ceci est important parce que les structures de données comme les tables de hachage de s'appuyer sur l'existence d'une classe de base commune. Vous pourriez mettre en œuvre une version pour un nominal de la classe de base, mais c'est un peu moins utile.
Java
Java a également été mentionnée. Beaucoup de gens aiment à détester Java et c'est vrai que la langue est extrêmement détaillé et manque de quelques de la de la plus moderne des fonctionnalités du langage (par exemple, des fermetures) mais rien de ce qui compte vraiment. Java est statiquement typé et a la collecte des ordures. Cela signifie que le compilateur Java va attraper de nombreuses erreurs qui typées dynamiquement langues ne va pas (jusqu'à l'exécution) et il n'y a pas de traiter avec la segmentation des défauts (qui n'est pas à dire que vous ne pouvez pas présenter une fuite de mémoire en Java; vous pouvez bien évidemment). Je pense que Java est un excellent choix.
C#
C# la langue est comme une version plus moderne de Java. Comme Java, il est géré (garbage collector) intermédiaire langage compilé qui s'exécute sur une machine virtuelle. Toute autre langue énumérés ici, à l'exception de C/C++ aussi s'exécuter sur une machine virtuelle, mais Python, Ruby, etc sont interprétés directement plutôt que compilés en bytecode.
C# a les mêmes avantages et inconvénients que Java, dans le fond.
Haskell ( ... )
Enfin, les langages fonctionnels: Haskell, OCaml, Régime/Lisp, Clojure, F#, etc. Ces réfléchir à tous les problèmes dans une manière très différente et sont vaut la peine d'apprendre à un certain point, mais encore une fois on en revient à ce que vous voulez apprendre: la programmation fonctionnelle ou de structures de données? Je collerais à l'apprentissage d'une chose à la fois, plutôt que de confondre la question. Si vous ne vous en apprendre un langage fonctionnel à un certain point (que je recommande), Haskell est un excellent choix.
Mon Avis
Choisissez Java ou C#. Les deux ont gratuit, excellente Ide (Eclipse, Netbeans et IntelliJ Community Edition pour Java, Visual Studio Express pour le C#) qui font de l'écriture et l'exécution de code d'un composant logiciel enfichable. Si vous n'utilisez aucun de données native structure plus complexe qu'un tableau et tous les objets que vous vous écrire, vous apprendrez essentiellement la même chose que vous feriez dans C/C++, mais sans avoir à gérer la mémoire.
Laissez-moi vous expliquer: extensible table de hachage doit être redimensionnée si suffisamment d'éléments sont ajoutés. La mise en application qui oblige à faire quelque chose comme le doublement de la taille de la sauvegarde de la structure de données (généralement un tableau) et la copie des éléments existants. La mise en œuvre est essentiellement la même dans tous les langages impératifs, mais en C/C++, vous aurez à traiter avec la segmentation fauls lorsque vous n'avez pas à allouer ou libérer quelque chose correctement.
Python ou Ruby (il n'a pas vraiment d'importance qui) serait mon prochain choix (et très proche pour les deux autres) tout simplement parce que le typage dynamique qui pourrait être difficile au premier abord.