views:

1148

answers:

21

So I am a Computer Science student and in about a week or so... I will be retaking a Data Structures course, using C++ for applying the theory. Yes, I did say "retaking". I took the course last Fall and I feel like there is more that I need to learn. Being a student, I feel that I MUST know the basics because it will be much easier to understand new concepts in future classes by already knowing the basic concepts... not having to relearn every time.

The first time around, I had no experience in C++ and the course expected us to be coding by the end of the first week. I struggled getting through several of the first programming assignments (MPs). Needless to say, I got used to it and had little trouble with the syntax the remainder of the semester. But then the harder Data Structures came around and the theory (Big O), became the difficult part.

All in all it was a great experience, but I feel my problem was that I didn't develop good study habits. I did the MPs and showed up to lecture, but it seems like my heart wasn't there with me. I want to change this the second time around because looking back at the class, I did have a good time and I enjoyed the material. But I found myself spending too much time thinking about/setting up the data structure(s) when I needed to be spending the time thinking about how to put the data structure to use effectively.

Learning theory is difficult (mostly because it isn't so exciting) so how should I apply myself to truly understand the Data Structures covered class? I've always been a visual learner, an interactive learner... I don't want to spend time just doing my MPs. Rather, I want to spend my time in such a way that I truly learn/understand the concepts and then directly apply the knowledge.

I'm looking for any suggestions... perhaps advice on study habits that have worked for you in the past learning such concepts... or suggestions on good note-taking techniques... anything that you'd like to share :) ... and most importantly, how to prepare before the semester starts.

Please feel free to provide feedback even if an answer has been selected. I am looking for your advice... this is why I posted :) Thanks!


NOTE: Data Structures and Topics covered in the course: Lists, Stacks, Queues, Trees (different kinds), Hash Tables, Graphs, Searching/Sorting/Traversal techniques.


UPDATE: Here's a list of links and references compiled from the answers so far.

UPDATE 2: Here's a list of some more sources that I found:

+2  A: 

The only way to meaningfully learn data structures and algorithms is to see them applied to real-world problems and to use them to solve real-world problems. Coding them up into working applications -- even if they contrived -- will reinforce the theoretical knowledge such that you will stand a better chance of retaining the ideas and integrating them into your personal problem-solving approach.

Adam Crossland
I totally agree... and this goes back to what I said about myself... I'm an interactive/visual learner and "coding them up into working applications" is a great way for me to learn. But due to time restrictions during the school year, I don't have much time to just sit down and create an application... so do you know of any interactive web apps perhaps that I can code a part of to make them work?
Hristo
@Hristo -- I am not suggesting that you create a full-blown, working and practical application for each data structure that you are learning. Rather, I mean that you should create some working code that utilizes the topic in a practical fashion. Also, you needn't bother with writing these as web applications. Writing console apps will do just fine for helping you to integrate these ideas into your brain for good.
Adam Crossland
That makes sense... thanks for your advice!
Hristo
@Hristo - you are very welcome, and as a software engineer with over 20 years of experience, let me say that the time that you spend now really working to make these concepts part of your everyday way of thinking will be rewarded a hundred-fold. Lazy engineers think that they can get by with the data structures and algorithms that are built-in to whatever langauge or framework they are using, but learning how to implement these ideas is really more about learning powerful problem-solving strategies. Keep giving this your all, and you'll do well.
Adam Crossland
Thanks Adam! That is really motivating :) I appreciate it!
Hristo
+14  A: 

Here's what helped me the most... Since you're a visual person, Google some visualized sorting algorithms, tree traversals, hashing, and etc to get a general idea of what's going on. After that, try making a simple program using different structures and experiment with different permutations of them--maybe for an example, you can make a linked list to start, then make it a circular linked list, then make it a doubly linked list, then make it a doubly circular linked list, and so on...

You just have to experiment with the structures, and as you do that, you'll start to see what data structures are appropriate for the applications you'll be developing.

Here are some nice references for you.. Sorting algorithms: http://www.sorting-algorithms.com/ Tree traversals: http://nova.umuc.edu/~jarc/idsv/lesson1.html Graph traversals: http://www.cosc.canterbury.ac.nz/mukundan/dsal/GraphAppl.html


As for efficiency (Big O analysis), it will come to you more or less naturally once you understand what is happening at the algorithmic level of each operation of the data structure.

One thing my university stresses is the development of our own implementation of data structures (which is bottom-up learning) without diving into the pre-established C++ templates (top-down learning). By making it from scratch, you really come to understand the overhead involved with inserting, removing, searching (traversing), and accessing data from a certain structure, and that will help your intuition when designing a system in the future.

danyim
Oh Wow... this looks awesome. Thanks! Do you know of any sources on Graphs and Hash tables?
Hristo
+1. Some good links there.
Stargazer712
I added a graph traversal link.
danyim
That is great stuff! Thanks a lot!
Hristo
+7  A: 

Practice, practice, practice.

The first piece of advice that I have for you is to become as proficient as possible at C++.

Data Structures and Programming are two very different topics. If you find yourself struggling with programming, it is unlikely that you will be able to comprehend the data structures.

How do you become proficient in C++? Practice, practice, practice. Program everything. Learn everything you can about it. Write dozens of small programs. Anything you can do to become comfortable with C++.

If you become proficient at C++, then I assure you that data structures will become easier. (Notice that I didn't say easy, I said easier :) )

Stargazer712
Good point... and I totally agree. Practice is super important. My only problem was that I had little time during the school year to even sleep :) So it has been difficult to make time for what needs to be done. But as you said, it won't be easy.
Hristo
No one said school was easy :). Good luck to you next semester.
Stargazer712
Thanks! I'll remember... "Practice, Practice, Practice!"
Hristo
+1  A: 

If you can visualize the implementation of data structures in real life, or to solve real life problems, then you may find it easier to understand.

Here are a few

  1. FIFO Linked List - This is the drive through at McDonalds
  2. LIFO Linked List - A stack of dinner plates
    • Searching and Sorting - A rolodex (if you're old that you've actually seen one of these things)
Raj More
don't know what a rolodex is :) but thanks for the examples. I have a good grasp on lists and arrays and such... my problems came in the later part of the course... when we started dealing with Trees, Graphs, Hash Tables, etc...
Hristo
+4  A: 

The key to learning data structures is to start with something small, and then build on that. Let's start with a simple C struct:

struct Person {
  char name[100];
  int age;
};

This data structure represents a person. You need to make sure you understand simple structure concepts such as these, and then you can move to bigger things.

When you start talking about data structures like stacks and queues, for example, first try to understand conceptually what the data structure is doing. For example, with a stack, we are using the LIFO principle, that is, Last In First Out. With a queue, we are using the FIFO principle (first in first out).

And then there's the one that trips a lot of people up, the linked list. You need to understand pointers well for this one, so before trying to tackle linked lists, start with something simple:

int* x;
int y = 10;
x = &y;

You should be able to look at that code and immediately know what it's doing. If you can't, then you're not ready to move to more advanced data structures like linked lists.

The main point I'm trying to make is you need to get the basics down cold, then build on those. It's also important to keep up with the class very diligently, ask your teacher or tutor if you are having troubles, and make sure you are on track each week and don't fall behind.

Computer Science classes are much like Math classes, each week usually builds on everything you've learned from the previous N weeks. So if you aren't understanding a key concept, like pointers for example, then you are going to have major struggles the remainder of the semester.

dcp
Thank you for your response! I guess I'm happy to say that I understand everything you wrote about... I'm comfortable with structs, lists, arrays, stacks, and queues. The really troublesome data structures were towards the middle of the course, when I was being exposed to Trees, Graphs, Hash Tables, etc.
Hristo
Yes, as you get into more complex data structures, there are more concepts to grasp, for sure. However, if you understand pointers well and the core concepts, then all of these advanced data structures just build on those key concepts. It sounds like you just need to put some more time into it. I remember staying up all night many times working on programs for my CS classes, but those were the times I learned the most, and honestly, the times I look back on as some of the most important educationally. Good luck!
dcp
Thanks! I think you are right... I need to spend more time on this material. Even though I spent many hours on my MPs, sometimes pushing 20-30 hours and going to sleep at like 3 or 4am, I agree that I learned a lot from just looking things up. I just felt like that was inefficient.
Hristo
+1  A: 

Here is a nice article to get you started: http://www.codeproject.com/KB/cpp/linked_list.aspx .Start with a simple linked list. It's very easy and you will understand it much easier than the other data structures. The Stack and Queue are maybe conceptually even easier but they are based on the simple linked list. Then you can move to double linked lists and trees. Looking forward to see your coding questions, Good Luck! :)

John Paul
Thanks! This seems like a great source to look over before the semester begins. Do you know of anything similar that deals with the more complicated data structures, such as Graphs, Hash Tables, etc...?
Hristo
All you have to do is search :) http://www.codeproject.com/KB/architecture/treedata_class.aspx Have fun!
John Paul
+2  A: 

I would recommend getting a good book on algorithms ('Introduction to Algorithms' by Cormen et al. would be my recommendation). Through the book you will both develop and put to use different data structures and you will most probably realize what each structure is good for. Data structures are only useful as means to achieve a different goal: solving a particular problem.

Depending on how much time you have or want to spend on it, you can try to get problems from different programming contests like the ACM ICPC. Most of the problems will require you exercise this knowledge. Note that both algorithms and data structures are language agnostic, so if you have good knowledge of any other language just use it.

David Rodríguez - dribeas
Joel
Kudos on the ACM reference... unfortunately I do not have much time during the school year. But I am planning to throw myself into more ACM and definitely taking a look at the book you recommended. Thanks!
Hristo
I took a look at the book you recommended and it seemed overwhelming. It does look like THE book for algorithms but it just seems too GIANT. I did, however, order Robert Sedgewick's book. http://www.amazon.com/gp/product/0201510596/ref=oss_product What do you think?
Hristo
+1  A: 

If you're a visual learner then ask your instructor for more diagrams. You might ask other students if you can study with them. Perhaps one of them can explain things to you in a way you can grasp more easily

Jay
Thanks. That makes sense.
Hristo
+2  A: 

In my opinion, these things are better off learned on-the-job, or through experience than in a theory course. Most times, while I was in school, working hard to stay ahead of the curve was the important part, which I think is similar to the experience that you have gone through. While it's commendable that you want to understand it thoroughly, as long as you know where to find good reference material when you need it, then the course has achieved its objective.

Most classes will build on the knowledge that you've gained in past classes. You'll run into these details again in your studies and your professors should be able to help you apply what you've learned in the past to your current classwork. As an interactive learner, office hours, internships and mentor opportunities seem like better ways to get the information you want.

Good luck!

theproxy
I agree that such concepts are better learned on-the-job. The problem with that is when I'm at a career fair and a recruiter asks me how to implement a Stack using 2 Queues, or to read some code about Hash Tables and recite what it does, I need to be able to do that without hesitating. Unfortunately, my summer internship hasn't been very CS intensive, mostly Web-oriented work (I prototyped an online chat system similar to Facebook Chat for example).
Hristo
+4  A: 

I like dcp's answer.

The best way to wrap your head around data structures is to write mini examples. Even if you copy them from your book, if you can get them to work and compile, and you typed them in with your own fingers, you will learn a lot.

As you read your book, and after each lecture, write the shortest programs you can that create and work with (display, use, etc.) the data structure you just learned about.

Then when you have to do your actual assignments you'll learn even more as you try and take your mini examples and plug them into the solving of the assignment problems.

I think writing the shortest / smallest possible piece of working code for individual data structures is very useful. Also, don't be afraid to copy code (for your own edification, not for your turned in assigments).... If you copy by typing and not copy pasting, you do end up learning a lot, since it forces you to look at each character in the code.


If entire data structures seem like "too much" to wrap your head around, then start by writing mini examples of the components of the Data structures. So store a book title with a pointer. Then store many book titles with pointers to pointers. Read a book title with square bracket notation and pointer arithmetic. Use recursion in simple functions where it is clear what is going on..... For example recursion to show the factorial of a number is simpler to wrap you head around than recursion to show a binary tree (in my opinion).....

You'll see what your problem areas are, and try and isolate them to as small and specific of a thing as you can, and then write as short a program that you can that deals with that problem area..... and then build up.

Your lectures are about entire data structures... giant Cummulus cloud banks of theory.... so, essentially they are top down. Isolating little problems of syntax and usage in mini problems is bottom up. So your teacher helps you attack from the top, you attack from the bottom by practicing, and pretty soon there's nothing in the middle!

Peter Ajtai
Thank you! That makes sense... mini examples... little functional parts that I could reuse to build bigger functional parts until I get it down.
Hristo
And when you have your mini programs you can use a debugger and/or log statements to see what is going on and when. Which sometimes fills in the missing pieces from the descriptions.
Fabio Fracassi
+1  A: 

A good resource is The NIST Dictionary of Algorithms and Data Structures. You aren't going to sit down and memorize all this information, and you shouldn't use it to avoid coding up your own structures, that would completely void the value of the class, but this site serves as a great reference because it links the data structures with the algorithms that utilize them and also shows some variants, which provides insight into how you can modify the structures for other uses.

Hope that helps. Good luck.


Jim
Oh wow... Thanks! This looks great! I'll bookmark it right away!
Hristo
+8  A: 

You have received some interesting links and ideas already. I hope I can provide a little different point of view:

I learned to visualize and "like" data structures by being taught that computer memory is like a really long list. The structures then have different layout in the memory. By visualizing the structures in the memory, it became obvious to me (and interesting) how they work. Knowing the data layout in memory is incredibly important for a programmer as today's continuously growing machines are often halted by memory-access. A good memory-layout easen the burden for the CPU to fetch the data from the memory so that the CPU doesn't have to wait for data to arrive.

Data structures is the layout of the data in a memory. Consider memory as a long list, just like a shopping list but without the entries.


0...
1...
2...
3...
4...
5...
6...

When you put structures into the memory, they essentially fill up these slots in memory.

A list is very simple, it just fills the memory-list from the top and down:


0 Element 0
1 Element 1
2 Element 2
3 Element 3

Although sometimes you want to change element 2 to something else, maybe zero. That's the way lists work. You can access the data in the structure by knowing their index (in this case, 0 .. 3).

Stacks are different. You can only access the "top" of a stack by "pushing" an element to the top of it, or "poping" an element from the top of it. Pushing means adding another element and the old top becomes invisible. Poping means removing the top element and the one below it becomes visible.


0   [ Hidden data ]
.   [ Hidden data ]
.   [ Hidden data ]
.   [ Hidden data ]
n   [ Hidden data ]
n+1 Element 4

Linked lists are different. A linked list contains a pointer (index in the memory-list) to the data, and one pointer to the next element:


0 Data: Memory index 0x00000100
1 Next: Memory index 6
2 
3 
4 
5 
6 Data: Memory index 104
7 Next: Memory index 8
...
100 Data pointed to from first member
101
102
103
104 Data pointed to from second member

Queue's is like a more powerful stack, you have access to both the bottom and the top. You can only push items to the top and you can only pop items from the bottom.


0 (bottom) Element (ready to be popped)
1 [ Hidden data ]
2 [ Hidden data ]
3 [ Hidden data ]
.
.
.
n (top) (empty, ready to be pushed / be given data)

By visualizing the layout of each data-structure, they became a lot more obvious to me in how they require memory and how they really work ( also in the memory). I hope that my examples have given you some brief starting knowledge for you to base your future studies on. As a final example on data structures, I will give you an unbalanced binary tree that have had the following order of element insertion: 3, 2, 1, 10, 9, 8, 6, 5, 4, 7

The tree starts at memory address 100, since memory address 0 is invalid and I'll use that as a "no pointer".


100 Value: "3"
101 Left ptr: 103
102 Right ptr: 109

103 Value: "2"
104 Left ptr: 106
105 Right ptr: 0

106 Value: "1"
107 Left ptr: 0
108 Right ptr: 0

109 Value: "10"
110 Left ptr: 112
111 Right ptr: 0

112 Value: "9"
113 Left ptr: 115
114 Right ptr: 0

115 Value: "8"
116 Left ptr: 118
117 Right ptr: 0

118 Value: "6"
119 Left ptr: 121
120 Right ptr: 127

121 Value: "5"
122 Left ptr: 124
123 Right ptr: 0

124 Value: "4"
125 Left ptr: 0
126 Right ptr: 0

127 Value: "7"
128 Left ptr: 0
129 Right ptr: 0

Hope that helps!

Simon
whoa... this was mesmerizing Simon! Totally unique approach to answering my question. Thanks a lot... and that makes so much sense! It all ultimately comes down to memory and if you understand how things work in memory, then the rest should be easy. I'll definitely do this when I'm back in the class or even before I start. Thanks!
Hristo
No problems! I'm glad it helps.
Simon
+1  A: 

I can remember my first data structures course. I remember being a bit overwhelmed at first.

I was more of a visual learner. To better grasp the material it really helped to see pictures. I used to draw out the steps of inserting, deleting and iterating through data structures such as a linked list or queue. It took up a lot of paper before I was done, but it was so worth it.

Once I got down drawing the process of insertions and what nots, the transition to actually programming the data structure was much easier.

Being able to visualize what was going on in memory really helped. And, as others mentioned before me: practice, practice, practice!

That there is a big part of success.

Good luck!

townsean
Yeah... I also was the drawer. I mean, I understood the process of inserting and removing, etc..., but for me, it was hard to recite that under the pressure and time constraints of the exam. but thanks... I will keep on drawing :)
Hristo
+1  A: 

Not sure this is any help, really, but it may be somewhat encouraging.

I was in the same boat when I took Data Structures 4 years ago. I went through the class with enough knowledge to get by and get the B, at least, in the class even though I didn't understand a lot of it.

I did not understand templates, linked lists, 'this' pointers, and really didn't understand pointers in general that well either, which greatly hindered my ability. I miraculously did what was required on the homework and tests (although test scores were still low for everyone and my teacher wound up curving them) and finished with a B.

After that I went on to take other classes for a few years. I found that in these classes different concepts were taught separately that helped me understand them better. Algorithms taught more about sorting and Big O, Assembly taught more about what was going on 'under the hood' of the computer which helped me understand pointers, etc.

I realized the second to last semester of my fifth year that I pretty much knew all the concepts from Data Structures and I hadn't even spent any extra effort to learn them, at least not from the standpoint of going back and trying specifically to understand Data Structures, if that makes any sense.

Without any real effort I wound up writing a templated, linked-list stack and queue for a couple of homework assignments in Operating Systems and I understood them. It blew me away. I'm positive it will be the same for you. Give it time and focus on other classes and it will all click. It seemed to take forever for it all to click for me, but it did.

Hope that helps.

Mike Webb
@Mike... Thanks for your response. I agree that with enough practice and exposure to the material in the future, I'll be up to speed. However, I feel that I need to know this now because it will make my life in the near future MUCH easier!
Hristo
+1  A: 

Honestly, I'm a self-taught C++ programmer originally (with my primary reference being the Source game engine's public-domain code from Half-Life 2), and I learned much of what got me through Data Structures by drawing up diagrams and reading comments and code.

Maybe I'm just a prodigy or something, because it always seemed to come relatively easy to me, but I learned during a LOT of time spent reading, thinking, and analyzing what the particular uses of each structure could be, and why each structure exists as something separate from the other data structures in the first place.

Having written some serious code projects (ie. Connect Four and a side-scrolling space shooter, as well as 3D isometric plotters and 2D drawing programs) on the severely-limited TI-83 Plus calculator in high school (p.s. Using TI-Basic, not Assembly), I realized what sorts of operations were more efficient, and I realized how limited the built-in list system (a basic Vector) was for data storage in certain situations. I also figured out how Big-O worked when I tried timing a program's runtime with different-size lists of input.

Practice, think about things as you are doing them, and try to figure out how and why they work, and never be afraid to get down and dirty with testing. After all, what is science without experimentation?

Shotgun Ninja
@Shotgun... several others have mentioned that practice is key. Thank you for your response. I think you're right... I'm going to have to beat this class up to death, lots of practice. Thanks.
Hristo
A: 

Practically speaking, I find that data structures require a solid understanding of pointers and memory.

For instance, you should be able to grok why the below linked list doesn't work in under a minute.

But, to understand why it doesn't work, you have to understand how memory is laid out in C and C++, and to understand intuitively the concept of a pointer.

Some people like pictures and drawing out pictures. Other people like to watch the MIT OpenCourseware - I recommend giving it at least a try.

class node
{

  int data;
  node* next;

  node* addnode()
  {
    node newnode;
    this->next = &newnode;

    return &newnode;
  }
};

This is an approximation of a (bugged) implementation of a linked list I wrote about 10 years ago when I was learning data structures.

And as a final note, practice and theory are the yin and yang of a quality programmer/developer/computer scientist. You can't be truly proficient without both.

Paul Nathan
@Paul... thanks for the response. I think you make a valid point, and that the key to understanding this is pointers and how things work in memory. I totally agree and its a tricky business :). So why doesn't the above implementation work? Is it because there has been no memory allocated to `newnode` and when it is returned, since it is a local variable, the memory address returned is garbage, or potentially garbage if not right away?
Hristo
@Hristo: newnode is allocated on the stack, so that portion of memory is 'invalid' after the closing brace of the function, leaving you with a reference into stack variable memory. The solution is to change the declaration to `node* newnode = new node;` and then remove the references. Of course, that leaves you with a linked list allocated on the heap, so you will need to `delete` each node later on.
Paul Nathan
Right... that's what I said... or at least had in mind. By no memory allocated, I meant no `new` keyword used to allocate heap memory. I know local variables are stack variables, so when the `addnode()` is finished, its stack memory can be reused so the returning variable is invalid.
Hristo
Also, this->next may already point to some node, if "this" is not the last node in the list. You can make newnode point to that node, by assigning this->next to newnode->next, before overwriting it. This makes the operation an insertion though.
Gnafoo
Good point. If `this` is in the middle of the list, `addnode()` will break the list... not something that should happen. Good catch.
Hristo
+1  A: 

When I taught programming, I always referred the Demystified books to my students.

I suggest you read:
- Data Structures Demystified
- OOP Demystified

These two books do a good job at breaking down data structures and OOP principle in simpler easy to read terms, with easy to follow examples. It's a good overview, but it does not go into the data structures supplied by the STL.

Dennis Miller
It is great to get a perspective from the other side. Thanks for your response. I'm not worried about data structures supplied by the STl... I have to write everything myself for this class.
Hristo
A: 

If you have problems with the O-notation, then 'Introduction to algorithms' by Cormen et.al. introduces these theoretic concepts in an easy to understand style. Well, this book is basically the bible for basic data structures. The proofs of runtime/space bounds are always presented in a very instructive fashion.

As always, if you study such book, do not just read it, but try to work on most of the exercises. Usually, doing this is very effective for learning the stuff.

Another general technique: try to join a local study group of 2-3 other students - usually, discussing the material with others (face to face) and while trying to explain the self-studied material to peers gives you a lot of hints, which things you need to cover more.

To master C++ for the exercises, 'The C++ Programming Language' by Stroustrup gives a good introduction and reference to the various language concepts. Since C++ is such a multi-paradigm language, beginners often are confused what of the concepts actually to use in practice to solve certain problems. To help with that 'Effective C++' by Scott Myers is a good start.

If your course makes heavy use of the STL, then there is 'Effective STL' as well. Scott Myers writing style is usually regarded as very 'fitting' for beginners.

maxschlepzig
+1  A: 

One thing you always need to remember, is that data structures don't just exist. They were invented to fit a need, which therefore means they are good for some reasons, but not for others.
Find out what those reasons are, what the data structure is good for, try to figure out the Big O for the operations before you will be told them.
Always compare data structures. Even with the simplest of them - An array. Take that as a starting point, and compare every data structure you find to an array. Sometimes you`ll find little tricks which help you avoid using the big data structure altogether.
For me, what helped me understand a lot of data structures and algorithms was the applet here, and I hope it will help you too: Applet

Rubys
wow... that applet looks incredible. Thanks so much!
Hristo
A: 

To me the best book I've found (so far) for understanding data structures is Steven Skiena's The Algorithm Design Manual.
Aside from the first part covering algorithm analysis, algorithm & data structures the second part is absolutely invaluable in finding (or at least narrowing down) the proper data structure/algorithm for solving a problem.

Eugen Constantin Dinca