Computational thinking is a way of thinking like a computer in order to help you solve problems and, more importantly, design algorithms for a computer to follow in a way that lets you solve other similar problems much more quickly.
There are two basic steps to computational thinking:
It's also important that the problem is efficient (runs quickly and preferably the runtime doesn't increase too quickly with scale) and correct (The program reliably gives the correct answer)
There are several important components to computational thinking:
Abstraction involves removing unnecessary details from the problem at hand. This is one of the most important components of computational thinking as it can dramatically simplify the problem you are trying to solve, and has the capability to create more general algorithms that can apply to completely different areas. For example, suppose you're trying to write a program to give the tax bracket of someone in a database based on various characteristics. The database may contain all kinds of information, such as:
However, most of this information is completely unnecessary. To calculate tax, a program will probably only need to know income, employment status and maybe address.
Another good example of how abstraction is incredibly useful for programming is programming languages themselves: In assembly language/machine code, you need to worry about memory addresses and the structure of the CPU itself. A low level language like C or Rust abstracts away a lot of this so that you don't need to worry at all about the CPU, but memory managemtn is still important. Meanwhile, a high-level language like Python or Javascript abstracts away memory management as well, and provides higher-level abstractions such as classes which let the programmer focus purely on the problem at hand rather than the limitations of the system (most of the time).
Abstraction can also be used to generalise solutions, such as the famous Seven Bridges of Koenigsburg problem, which laid the foundations for modern graph theory. Euler showed that these two images can actually represent the same thing, but mathematicians much prefer the second one for reasons which I hope are obvious:

Alternatively, data abstraction allows you to create abstract data types without having to worry about the underlying representation.
A problem is often much easier to solve and integrate into larger solutions if you think about certain things. Mainly:
Now that we've abstracted the relevant data and thought about preconditions for the program to work, we need to work out the sequence of steps to be taken by the algorithm. Confusingly, this is called procedural abstraction.
A good procedure means that the programmer doesn't need to know how the procedure works, just what to put in, what they'll get out and that the procedure works. This is called the procedure interface.
Another important part of procedural thnking is problem decomposition. Break the problem down into individual parts that don't need each other to work. For example, if we're drawing a map, you can decompose the problem into drawing the outlines of countries, as well as filling them in, and writing text labels on the canvas. All of these need to be dealt with, but can be dealt with separately. Top-down design means that you break a problem down into major tasks in this way, and then break those tasks down further using a hierarchy chart.