[Disclaimer: All Rights Reserved. You are welcome to reprint it. Do not use it for commercial purposes. Contact Email: feixiaoxing @ 163.com]
Algorithms are the lives of computers. Without algorithms, there will be no software, and computers will become a cold machine with no practical value. Many people think that algorithms are mathematical content, which is especially difficult to learn. We cannot think this is wrong. However, we also know that software is a composite technology. If a person only knows the algorithm but cannot implement it well using programming languages, then excellent algorithms cannot play a role. Only when a person has good computer knowledge and mathematical knowledge can he continue to improve in algorithm learning. No matter how simple the algorithms are, you must practice them by yourself. Only by constantly recognizing and discovering errors can you continuously improve your programming capability and business level.
There are two main purposes for writing algorithms one by one: first, make sure that all of our algorithms can be learned and understood. Second, ensure that our algorithms are robust and testable. Therefore, in the process of writing, our algorithm development process is accompanied by the addition of test cases. The code without test cases is just a piece of unordered characters and has no value.
In fact, any algorithm has its own application environment and Application Scenario. No algorithm can be applied to all scenarios. I hope you can understand this. At the same time, we also need to know that complex algorithms are composed of common algorithms. Without common algorithms, there will be no complicated algorithms. Therefore, complexity becomes simpler and the complexity becomes smaller, this is the basic idea of algorithm grouping and recursion.
Let's start with an array search function. Starting from the simplest function construction:
Int find (int array [], int length, int value)
{
Int index = 0;
Return index;
}
Int find (int array [], int length, int value)
{
Int index = 0;
Return index;
} Here we can see that the lookup function is just a common function. The first thing to judge is the validity of the parameter:
Static void test1 ()
{
Int array [10] = {0 };
Assert (FALSE = find (NULL, 10, 10 ));
Assert (FALSE = find (array, 0, 10 ));
}
Static void test1 ()
{
Int array [10] = {0 };
Assert (FALSE = find (NULL, 10, 10 ));
Assert (FALSE = find (array, 0, 10 ));
} Here we can see that we didn't judge the validity of the parameter. How should we modify the original search function?
Int find (int array [], int length, int value)
{
If (NULL = array | 0 = length)
Return FALSE;
Int index = 0;
Return index;
}
Int find (int array [], int length, int value)
{
If (NULL = array | 0 = length)
Return FALSE;
Int index = 0;
Return index;
} Seeing the code above, it indicates that we have determined the entry parameters. Then we will start to write the code.
Int find (int array [], int length, int value)
{
If (NULL = array | 0 = length)
Return FALSE;
Int index = 0;
For (; index <length; index ++ ){
If (value = array [index])
Return index;
}
Return FALSE;
}
Int find (int array [], int length, int value)
{
If (NULL = array | 0 = length)
Return FALSE;
Int index = 0;
For (; index <length; index ++ ){
If (value = array [index])
Return index;
}
Return FALSE;
}
The above code is almost complete. How should I write the test case?
Static void test2 ()
{
Int array [10] = {1, 2 };
Assert (0 = find (array, 10, 1 ));
Assert (FALSE = find (array, 10, 10 ));
}
Static void test2 ()
{
Int array [10] = {1, 2 };
Assert (0 = find (array, 10, 1 ));
Assert (FALSE = find (array, 10, 10 ));
} After running all the test cases, let's see if there is anything to optimize the original code. In fact, we can convert an array into a pointer.
Int find (int array [], int length, int value)
{
If (NULL = array | 0 = length)
Return FALSE;
Int * start = array;
Int * end = array + length;
While (start <end ){
If (value = * start)
Return (start-array)/(sizeof (int ));
Start ++;
}
Return FALSE;
}
Int find (int array [], int length, int value)
{
If (NULL = array | 0 = length)
Return FALSE;
Int * start = array;
Int * end = array + length;
While (start <end ){
If (value = * start)
Return (start-array)/(sizeof (int ));
Start ++;
}
Return FALSE;
}
What if the above Code parameter must be of a common data type?
Template <typename type>
Int find (type array [], int length, type value)
{
If (NULL = array | 0 = length)
Return FALSE;
Type * start = array;
Type * end = array + length;
While (start <end ){
If (value = * start)
Return (start-array)/(sizeof (type ));
Start ++;
}
Return FALSE;
}
Template <typename type>
Int find (type array [], int length, type value)
{
If (NULL = array | 0 = length)
Return FALSE;
Type * start = array;
Type * end = array + length;
While (start <end ){
If (value = * start)
Return (start-array)/(sizeof (type ));
Start ++;
}
Return FALSE;
} Does the test case need to be modified again?
Static void test1 ()
{
Int array [10] = {0 };
Assert (FALSE = find <int> (NULL, 10, 10 ));
Assert (FALSE = find <int> (array, 0, 10 ));
}
Static void test2 ()
{
Int array [10] = {1, 2 };
Assert (0 = find <int> (array, 10, 1 ));
Assert (FALSE = find <int> (array, 10, 10 ));
}
Static void test1 ()
{
Int array [10] = {0 };
Assert (FALSE = find <int> (NULL, 10, 10 ));
Assert (FALSE = find <int> (array, 0, 10 ));
}
Static void test2 ()
{
Int array [10] = {1, 2 };
Assert (0 = find <int> (array, 10, 1 ));
Assert (FALSE = find <int> (array, 10, 10 ));
}
So, let's summarize:
(1) Our algorithms must be verified using test cases.
(2) Any optimization should be based on testing.
(3) The test and code should be synchronized.
(4) The algorithm runs successfully step by step. The success of each step must be established above the original success.