Seven common sorting, how many do you know? (Down)

A hundred people in the eyes of a hundred people, I am both an angel and a devil

On the road of life, you will always meet all kinds of people

They all say different things about us

Just like a good person sees a hard-working person, they will feel that he is very self-disciplined and hard-working

And some people who have nothing but want to lie down, will feel that he is very curly.

What we have to do is not to change the goals of ourselves because of the eyes of those who lie flat

But quietly trying to become someone else's dream


1. Bubble sort 

2. Quick Sort

3. Merge Sort

1. Bubble sort

Sort ascending: 

Ascending order: For each comparison, the largest number of the compared numbers will be returned

Descending order: For each comparison, the smallest number of the compared numbers will be placed in place

Thinking: If it is already in order or close to order, is it necessary to compare n-1 times? (If so, it would be too troublesome to compare n-1 times!)

Solution: We can use a variable record, which defaults to 0 if there is no exchange during a trip, and 1 if an exchange occurs. Then judge whether this variable is 0, if it is 0, jump out of the comparison loop, otherwise continue to execute the loop comparison. 

 Code:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//交换
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}


//冒泡排序
void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n; j++)
	{
		int exchange = 0;
		for (int i = 1; i < n - j; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				exchange = 1;//避免不必要的排序
			}
		}
		if (exchange == 0)
		{
			break;
		}
	}
}
void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

int main()
{
	int a[] = { 7, 3, 2, 6, 8, 1, 9};
	int size = sizeof(a) / sizeof(int);
	BubbleSort(a, size);
	PrintArray(a, size);
	return 0;
}

Summary of the characteristics of bubble sort:

  1. Bubble sort is a very easy to understand sort
  2. Time complexity: O(N^2)
  3. Space Complexity: O(1)  
  4. Stability: stable

 


2. Quick sort

2.1 Digging method 

Note: Generally, the first or last number is regarded as a keyword, and the value smaller than the keyword key is found to the left, and the value larger than the keyword key is found to the right.

Idea: first assign the first number as a keyword to the key, and then the position of the first number is a pit, look for the number smaller than the keyword from the end to the left, and after finding it, put it in the pit, and then it The location becomes a new pit, and then find a number larger than the keyword from begin to the right and put it into the new pit to continue to form a new pit, and so on until end, begin and pivot point to the same position and put the key in this place , this sorting will bring a number back to its place. Then use the same method to make the numbers on the left of this number sorted, the numbers on the right are sorted, and the entire array is sorted.

Thinking: Why add begin < end ?

Because when begin = end, the key value is also returned, and then the key is less than the key value before the key, and the key value is greater than the key value. So no need to look across.

 Consider: What is the worst case for quicksort? When it is ordered, the time complexity is O(N^2).

So how do we solve this problem? ? ?

Use the three-digit method.

The Chinese-French idea of ​​taking three numbers: compare the number of the first subscript with the number of the middle subscript and the number of the last subscript, and return the middle number (not the largest nor the smallest).

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//交换
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//三数取中法
int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) >> 1;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else // a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}

//快速排序之挖坑法
void QuickSort(int* a,int left,int right)
{
	if (left >= right)
	{
		return;
	}

	int index = GetMidIndex(a, left, right);
	Swap(&a[left], &a[index]);

	int begin = left;
	int end = right;
	int key = a[begin];
	int pivot = begin;
	while (begin < end)
	{
		while (begin < end && a[end] >= key)
		{
			end--;
		}
		a[pivot] = a[end];
		pivot = end;
		while (begin < end && a[begin] <= key)
		{
			begin++;
		}
		a[pivot] = a[begin];
		pivot = begin;
	}
	a[pivot] = key;

	QuickSort(a, left, pivot - 1);
	QuickSort(a, pivot + 1, right);

}
void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}


int main()
{
	int a[] = { 7, 3, 2, 6, 8, 1, 9};
	int size = sizeof(a) / sizeof(int);
	QuickSort(a, 0, size - 1);
	PrintArray(a, size);

	return 0;
}

 

 2.2 Left and right pointer method

Idea: find the ones smaller than the keyword to the left, find the ones larger than the keyword to the right, and exchange after finding them 

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//交换
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//三数取中法
int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) >> 1;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else // a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}

//快速排序之左右指针法
void QuickSort2(int* a, int lefti, int righti)
{
	if (lefti >= righti)
	{
		return;
	}

	int index = GetMidIndex(a, lefti, righti);
	Swap(&a[lefti], &a[index]);

	int left = lefti;
	int right = righti;
	int key = left;
	while (left < right)
	{
		while (left < right && a[right] >= a[key])
		{
			--right;
		}
		while (left < right && a[left] <= a[key])
		{
			++left;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[key], &a[left]);

	QuickSort2(a, lefti, left-1);
	QuickSort2(a, left+1, righti);
}
void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}


int main()
{
    int a[] = { 7, 3, 2, 6, 8, 1, 9};
	int size = sizeof(a) / sizeof(int);
	QuickSort2(a, 0, size - 1);
	PrintArray(a, size);
	return 0;
}

 

 2.3 Front and back pointer method

Idea: front finds a value larger than the key in the front, when after++ is found, then exchange the two values ​​(the small one is pushed forward, the larger one is pushed back)

 

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//交换
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//三数取中法
int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) >> 1;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else // a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
//快速排序之前后指针法
void QuickSort3(int* a, int lefti, int righti)
{
	if (lefti >= righti)
	{
		return;
	}

	int index = GetMidIndex(a, lefti, righti);
	Swap(&a[lefti], &a[index]);

	int after = lefti;
	int front = lefti + 1;
	int key = lefti;

	while (front <= righti)
	{
		if (a[front] < a[key])
		{
			after++;
			Swap(&a[front], &a[after]);
		}
			front++;
	}
	Swap(&a[after], &a[key]);
	QuickSort3(a, lefti, after - 1);
	QuickSort3(a, after + 1, righti);

}

void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}


int main()
{
	int a[] = { 7, 3, 2, 6, 8, 1, 9};
	int size = sizeof(a) / sizeof(int);
	QuickSort3(a, 0, size - 1);
	PrintArray(a, size);

	return 0;
}

Summary of Quick Sort Features:

  1. The overall performance and usage scenarios of quick sort are relatively good, so I dare to call it quick sort.
  2. Time complexity: O(N*logN)
  3. Space complexity: O(logN)
  4. Stability: Unstable 

 


 3. Merge sort

Basic idea: Merge sort (MERGE-SORT) is an efficient sorting algorithm based on the merge operation, which is a very typical application of the divide and conquer method (Divide and Conquer). Merge the ordered subsequences to obtain a completely ordered sequence; that is, first make each subsequence ordered, and then make the subsequence segments ordered. If two sorted lists are merged into one sorted list, it is called two-way merge. 

 

#include<stdlib.h>
#include<stdio.h>
//归并排序
void _MergeSort(int* a, int left, int right, int* tmp)
{
	if (left >= right)
		return;

	int mid = (left + right) >> 1;
	// 假设 [left, mid] [mid+1, right]有序,那么我们就可以归并了
		_MergeSort(a, left, mid, tmp);
	_MergeSort(a, mid + 1, right, tmp);

	// 归并
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = left;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[index++] = a[begin1++];
		}
		else
		{
			tmp[index++] = a[begin2++];
		}
	}

	while (begin1 <= end1)
	{
		tmp[index++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[index++] = a[begin2++];
	}

	// 拷贝回去
	for (int i = left; i <= right; ++i)
	{
		a[i] = tmp[i];
	}
}

void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int)*n);
	_MergeSort(a, 0, n - 1, tmp);
	free(tmp);
}

void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}


int main()
{
	MergeSort(a, size - 1);
	PrintArray(a, size);
	return 0;
}

 Summary of the characteristics of merge sort:

  1. The disadvantage of merge is that it requires O(N) space complexity. The thinking of merge sort is more to solve the problem of external sorting in disk.
  2. Time complexity: O(N*logN)
  3. Space complexity: O(N)
  4. Stability: stable

 


 Sorting Algorithm Complexity and Stability Analysis

 

Guess you like

Origin blog.csdn.net/m0_66488562/article/details/124145727