# Time complexity and space complexity (data structure implemented in C language)

Keywords: C Algorithm data structure

# preface

Woo woo woo, the C language blog has been delayed for too long and has lost itself; Now I have to learn data structure again. If you have time to write a blog in C language! The data structure must be constantly! Well, sure, come on, Ollie!!!!!!

# 1. What is a data structure

Data structure is a way for computers to store and organize data. It refers to data elements with one or more specific relationships         A collection of primitives.

When implementing the project, you need to store some data in memory. For example, address book, you need to put each         People's information is stored for later viewing. Of course, there are many storage methods, each of which has its advantages and disadvantages          talk later.

# 2. What is an algorithm

It is a well-defined calculation process. It takes one or a group of values as input and generates one or a group of values as input               Out. In short, the algorithm is a series of calculation steps used to convert input data into output results.

Common algorithms are: sorting, searching, de duplication

# 3. Importance of data structure and algorithm

—— Say the important words three times, bold and focus

Especially important, especially important, especially important

# 1.1 how to measure the quality of an algorithm

For example, the Fibonacci sequence below

```long long Fib(int N) {
if (N < 3)
return 1;

return Fib(N - 1) + Fib(N - 2);
}```
The recursive implementation of Fibonacci sequence is very concise, but must simplicity be good? How to measure its good and bad?

# 1.2 algorithm complexity

When the algorithm is written into an executable program, it needs time resources and space (memory) resources. So measure

The quality of an algorithm is generally measured from two dimensions of time and space, namely time complexity and space complexity.

Time complexity mainly measures the running speed of an algorithm, while space complexity mainly measures the running time of an algorithm

Extra space. In the early days of computer development, the storage capacity of computer was very small. So I care about the complexity of space.

However, with the rapid development of computer industry, the storage capacity of computer has reached a high level. So now we

There is no need to pay special attention to the spatial complexity of an algorithm.

# 2.1 concept of time complexity

definition:

In computer science, the time complexity of an algorithm is a function, which quantitatively describes the running time of the algorithm. one

In theory, the time spent in the execution of an algorithm cannot be calculated. Only you put your program on the machine and run it

Get up before you know. However, the same algorithm runs on different computers and takes different time to learn drugs. algorithm

The execution times of the basic operation in is the time complexity of the algorithm.

Let's take a look at specific examples to see how much time complexity is

```// Please calculate how many times the + + count statement in Func1 is executed in total?
void Func1(int N) {
int count = 0;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j)
{
++count;
}
}

for (int k = 0; k < 2 * N; ++k) {
++count;
}
int M = 10;
while (M--) {
++count;
}
printf("%d\n", count);
}
```

analysis:

F(N)=N^2+2*N+10

N=1,F(N)=13;  N=10,F(N)=130;  N=100,F(N)=10210;  N=1000,F(N)=1002010;......

It can be seen that the greater the N, the least influence of the latter two items on the results; In fact, when we calculate the time complexity, we do not have to calculate the exact execution times, but only the approximate execution times. Here, we use the asymptotic representation of large O.

# two point two   Asymptotic representation of large O

Large O symbol: a mathematical symbol used to describe the asymptotic behavior of a function.
Derivation of large O-order method:
1. Replace all addition constants in the run time with constant 1.
2. In the modified run times function, only the highest order term is retained.
3. If the highest order term exists and is not 1, the constant multiplied by this item is removed. The result is large O-order.

In addition, the time complexity of some algorithms has the best, average and worst cases:
Worst case: maximum number of runs of any input scale (upper bound)
Average case: expected number of runs of any input scale
Best case: minimum number of runs of any input scale (lower bound)

For example, search for a data x in an array of length N
Best case: 1 time
Worst case: found N times
Average: N/2 times
In practice, the general concern is the worst-case operation of the algorithm, so the time complexity of searching data in the array                               Is O(N)

# two point three   Common time complexity calculation examples

Example 1:

```// Calculate the time complexity of Func2?
void Func2(int N) {
int count = 0;
for (int k = 0; k < 2 * N; ++k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
printf("%d\n", count);
}```
Yes 2N+10 Times, by deriving O The first-order method knows that the time complexity is O(N)

Example 2:

```// Calculate the time complexity of Func3?
void Func3(int N, int M) {
int count = 0;
for (int k = 0; k < M; ++k)
{
++count;
}
for (int k = 0; k < N; ++k)
{
++count;
}
printf("%d\n", count);
}```
Executed M+N times, with two unknowns M and N, and the time complexity is O(N+M)
Generally, N is used for time complexity calculation, but other M, K can also be used

Example 3:

```// Calculate the time complexity of Func4?
void Func4(int N) {
int count = 0;
for (int k = 0; k < 100; ++k)
{
++count;
}
printf("%d\n", count);
}```
The operation is performed 10 times. By deriving the large O-order method, the time complexity is O(1)

Example 4:

```// Calculate the following time complexity?
while(*str)
{
if(*str == character)
return str;
else
++str;
}
```

The best execution is once and the worst is N times. The time complexity is generally the worst. The time complexity is O(N)

Example 5:

```// Calculate the time complexity of BubbleSort?
void BubbleSort(int* a, int n) {
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}```

The best execution is N times, and the worst execution is (N*(N+1)/2 times. By deriving the large O-order method + time complexity, it is generally the worst, and the time complexity is O(N^2)

Example 6:

```// Calculate the time complexity of BinarySearch?
int BinarySearch(int* a, int n, int x) {
assert(a);
int begin = 0;
int end = n - 1;
while (begin < end)
{
int mid = begin + ((end - begin) >> 1);
if (a[mid] < x)
begin = mid + 1;
else if (a[mid] > x)
end = mid;
else
return mid;
}
return -1;
}```
The best execution is once, the worst is O(logN), and the time complexity is O(logN)
Binary search is particularly nb, but it needs to be done in an orderly manner

Example 7:

```// The time complexity of computing factorial recursive Fac?
long long Fac(size_t N) {
if (0 == N)
return 1;

return Fac(N - 1) * N;
}```

Through calculation and analysis, it is found that the basic operation recurses N times and the time complexity is O(N)

Example 8:

```// The time complexity of computing Fibonacci recursive Fib?
long long Fib(size_t N) {
if (N < 3)
return 1;

return Fib(N - 1) + Fib(N - 2);
}```

Through calculation and analysis, it is found that the basic operation recurses 2^N times and the time complexity is O(2^N)

# 3. Space complexity

Space complexity is also a mathematical expression, which is a measure of the temporary additional storage space occupied by an algorithm during operation.
Space complexity is not how many bytes the program occupies, because it doesn't make much sense, so space complexity is the number of variables. The calculation rules of spatial complexity are basically similar to the practical complexity, and the large O asymptotic representation is also used.
Note: the stack space (storage parameters, local variables, some register information, etc.) required by the function runtime has been determined during compilation, so the space complexity is mainly determined by the additional space explicitly applied by the function at runtime.

Example 1:

```// Calculate the spatial complexity of BubbleSort?
void BubbleSort(int* a, int n) {
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
```

Example 1 uses an additional space, so the space complexity is O(1)

Example 2:

```// Calculate the spatial complexity of Fibonacci?
// Returns the first n items of the Fibonacci sequence
long long* Fibonacci(size_t n) {
if (n == 0)
return NULL;

long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));
fibArray[0] = 0;
fibArray[1] = 1;
for (int i = 2; i <= n; ++i)
{
fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
}
return fibArray;
}
```

Example 2 dynamically opens up N spaces, and the space complexity is O(N)

Example 3:

```// Calculate the spatial complexity of factorial recursive Fac?
long long Fac(size_t N) {
if(N == 0)
return 1;

return Fac(N-1)*N;
}
```

Example 3 recursively called N times and opened up N stack frames. Each stack frame uses a constant space, and the space complexity is O(N)

Posted by nelsok on Fri, 15 Oct 2021 13:22:21 -0700