I don’t believe I can’t learn [Quick Sort]

1 Introduction

    Quick sort, this is a question that the company often asks during interviews. It is also a guy who has made me write it many times but just can't remember. I am determined to smash to the end and understand the quick sort thoroughly.

2 Basic ideas

    According to the information of teaching materials and various materials, quick sort is to divide the data to be sorted into two parts first. How to divide it?

    First randomly select a number from the data. This number is used as the object to be compared. The more specialized name is called the pivot. This pivot divides the entire data into two parts. One part is smaller than the pivot, and the other is the same. Bigger than the main element.

    The part that is equal to the principal element can be divided into a small group or a large group, and just keep the same before and after.

    Then, recursively continue the previous operations on these two sets of data until they can no longer be divided.

    For example:

    2,8,7,1,3,5,6,4

    We randomly choose a number, and the last one is 4, which divides the data into two parts, one part is 2, 1, 3, all less than 4, and the other part is 8, 7, 5, 6, all greater than 4.

    Then, the position of 4 is the final position, that is, the 4th position. No matter how it is sorted later, 4 is always in this position.

    Then, continue to sort the two sequences 2, 1, 3 and 8, 7, 5, and 6 according to the above rules.

3 Schematic

    Before uploading the code, let's see how to implement such a process through the code or through the steps according to the schematic diagram. Still use the above example, 2, 8, 7, 1, 3, 5, 6, 4

    Here we will use 4 pointers, namely p, r, i, j. Among them, p represents the left boundary of the array, r represents the boundary of the array, and i is used to mark data smaller than the principal element, that is, the data on the left side of i is smaller than the principal element, and the data on the right side of i is larger than the principal element. Yuan. j is used for traversal operations.

    

    When initializing, i needs to be set to p-1, j is set to p, the pivot is set to the last element and then the traversal starts;

                

    When traversing, you need to perform operations, the specific operations are:

    When the element of j is smaller than the pivot, i++, and then perform the exchange operation of the elements of i and j.

    This step is more difficult to understand. My explanation is this. In order to ensure that the left side of i is all elements smaller than the pivot, and the right side is all elements larger than the pivot, when j traverses, it encounters the elements smaller than the pivot Element, you need to change this element to the left of i

    And the right side of i are all elements greater than the pivot, so execute i++, and then perform the exchange operation, move the elements less than the pivot to the left of i;

               

    Continue to traverse j. If the element pointed to by j is greater than the pivot, no operation is required, just continue to traverse;

              

    At this time, j points to 1, which is less than pivot 4, execute i++, that is, i points to the position of 8, and then exchange the elements at positions i and j, that is, exchange 8 and 1, and get the following:

                  

    Continue to traverse, j points to 3, less than 4, execute i++, that is, i points to 7, and then exchange the elements at positions i and j, that is, exchange 7 and 3, and get the following:

                   

     Continue to traverse, 5 and 6 are both less than 4, no operation is performed. The traversal is completed as follows:

                  

    Then you need to put the pivot back to its own position, that is, exchange with the element at position i+1. This is easy to understand. The left side of i is smaller than the pivot, and of course it is swapped with the first element on the right. .

                   

4 code

    Through the above process, I will implement the code in C language. There should be three functions, one is the swap function Swap, the other is the partition function Partition, which divides the data into two parts, the position of the pivot is required to be returned, and the other is the sorting function QuickSort that is called recursively. code show as below:

//交换数组中两个位置对应的元素
void Swap(int *arr, int src, int dst)
{
    //位置相同不执行互换操作
	if (src != dst)
	{
		arr[src] = arr[src] ^ arr[dst];
		arr[dst] = arr[dst] ^ arr[src];
		arr[src] = arr[src] ^ arr[dst];
	}
}

//划分函数,将数组根据主元分为两部分
int Partition(int *arr, int left, int right)
{
	int i = left-1;
	for (int j = left; j < right; j++)
	{
        //以最后一个数据作为主元,将小于主元的数据交换到最左侧
		if (arr[j] <= arr[right])
		{
			i++;
			Swap(arr, i, j);
		}
	}
	
    //最后需要将主元放到它本身的位置上去
	Swap(arr, right, i + 1);

	return i + 1;
}

//递归排序函数
void QuickSort3(int *arr, int left, int right)
{
    //递归结束的标志,不能再继续划分为止
	if (left < right)
	{
		int p = Partition(arr, left, right);
        //这里p-1是因为p的位置已经是主元了,不用再排序了
        //如果不执行p-1而执行p,可能会造成死循环,导致栈溢出
		QuickSort3(arr, left, p-1);
		QuickSort3(arr, p + 1, right);
	}
}

    We call to test:

int main()
{
	int arr[8] = { 2,8,7,1,3,5,6,4 };

	QuickSort3(arr, 0, 7);

	for (int i = 0; i < 8; i++)
	{
		printf("%d\t", arr[i]);
	}

	printf("\n");

    return 0;
}

    Look at the result chart:

    

    Change another test method:

    

int main()
{
    int arr[MAX_NUM] = { 0 };

    //使用 0-1000的随机数,1000个数据进行排序测试
	srand((unsigned int)time(NULL));
	for (int i = 0; i < MAX_NUM; i++)
	{
		arr[i] =  rand() % 1000;
	}

	QuickSort3(arr, 0, MAX_NUM-1);

	for (int i = 0; i < MAX_NUM; i++)
	{
		if (i % 10 == 0)
		{
			printf("\n");
		}
		printf("%d\t", arr[i]);
	}
	printf("\n");

	system("pause");
	return 0;
}

    Test result chart:

    

    The result is a bit long. Looking at some screenshots, you can also see that the sorting is OK. Finally, add that in the worst case, that is, the data has been sorted, and the largest number is selected as the pivot, the time complexity is O(n^2), and in general, the time complexity is NlogN.

 

    The above is a personal summary, pure hand-playing, please criticize and correct any omissions. There is another kind of quick sort code implementation. It's too late. Let's write another day. You can see the function QuickSort3 in my code, which means there are still 1 and 2 haha. . .

Guess you like

Origin blog.csdn.net/kakaluote81/article/details/115339559