My algorithms class at UT was taught from it, very thorough and useful book.
This is the latest version of that text... at my school we call it "CLRS":
http://www.amazon.com/Introduction-A...0007631&sr=1-1
The second edition is more common & can probably be had for a good bit cheaper. It's missing a new section on multicore/parallel computing... but that section is very, very introductory so I wouldn't worry about it, lol. I think the pseudo-code was substantially improved btwn 2nd and 3rd editions too; that might be more of a concern.
That's the book that I learned out of. My only complaint is that the book is soooo wordy. (You can thank Leiserson for that.) But it is clear and generally does a fine job explaining a broad set of introductory algorithms topics. (One exception: the wiki article on Red-Black trees is more clear than CLRS on that topic, haha.)
Also, I would take a look at MIT's "OpenCourseWare" pages. You'll be able to see lecture notes, assignments (usually with solutions), etc. for a number of topics... good learning tool.
http://ocw.mit.edu/courses/electric...ntroduction-to-algorithms-sma-5503-fall-2005/
^^Undergraduate algorithms. A run of the mill undergrad algorithms class.
http://ocw.mit.edu/courses/electric...science/6-854j-advanced-algorithms-fall-2005/
^^Graduate algorithms. Quite a bit more challenging & the topics are more interesting too. And by quite a bit, I mean infinity-billion times more. (Can try
http://courses.csail.mit.edu/6.854/current/ too. Only issue is once the next class starts, lots of materials will get taken off the page.)
http://ocw.mit.edu/courses/electric...ience/6-856j-randomized-algorithms-fall-2002/
^^Randomized algorithms. I haven't taken this yet but I want to.
http://courses.csail.mit.edu/6.851/
^Graduate data structures. Has some pretty cool stuff. Some practical, some not so much.
Edit: I should add that using bubblesort isn't embarrassing unless your data sets are larger than 20-30 numbers or smaller than 6-7

(Larger and the divide & conquer methods start winning. Smaller and you're better off coding up all the possibilities manually.) Though as cogman said, selection sort is typically faster without being any more complicated--"faster" as measured from a theoretical POV and a practical one.
For an even better sorting algorithm...
http://en.wikipedia.org/wiki/Bogosort
And if you haven't looked up "tortoise vs hare" yet, (that isn't the actual name of the algorithm... I forgot who it's named after) try to solve this problem & you'll have discovered it for yourself
Suppose I give you a linked list (or more generally some representation of a directed graph); say each node contains an integer. You cannot modify the linked list, but you can step through the list nodes & read the integer they contain. The list is potentially extremely large, and I'm not telling you how large it is.
The problem: how quickly can you tell me if the linked list has a cycle? (Cycle = a list node points to a previous node or to itself, so that by always looking at node.next, you'll never reach "the end" of the list; i.e., tell me if the linked list has a last element.) And "quickly" means: how long will it take in terms of the number of nodes you read & how much storage will you require (storing 1 number is 1 unit of space).
Hint: the name "tortoise vs hare" has a lot to do with the answer!