Let me elaborate on Jeff's response, using the student/course example.
A database is meant to store FACTS. Say two of the facts are: John Doe takes
Math101, Jane Smith takes Chem102. Where do store these? Let's assume for the
sake of argument that you put them in the student table, like so:
John Doe (address, dob, etc.) Math101
Jane Smith (address, dob, etc.) Chem102
But now John Doe enrolls in Chem102 - where do we store that fact? Let's add
a field for the second course, like this:
John Doe (address, dob, etc.) Math101 Chem102
Jane Smith (address, dob, etc.) Chem102 NULL
How far do we take this? How many course fields do we create in the Student
table? OK, so maybe we can set a reasonable limit on number of courses and
create that many fields.
Now the teacher for Chem102 wants the list of students in her class. How do
we create it? Where in the student table do we find that information? It is
in a different place for each student, making the query difficult to write
and slow to execute. And your query would have to be rewritten if the course
limit per student changes.
A naive user might attempt to store each fact TWICE - once in the Student
table to create a list courses for each student, once in the Course table to
create a list of students in a course. Bad idea. First of all, duplicating
facts may lead to inconsistencies between the duplicates. What do you do if
Chem102 exists in John Doe's record, but John Doe is absent from the Chem102
record?
Second, you need to set a limit of students per course, so you know how many
student fields to create for each - typically this varies from course to
course. If you create fields for the largest course, how do you limit entries
for courses that allow fewer students? With this structure, merely writing a
query to count students for a course is non-trivial.
That's where the junction table comes in - it uniquely stores single facts
about TWO entities in your database, in a structure through which it is very
easy and efficient to search, report, count, calculate etc.