Common sorts

void Swap(int* p, int* q)
{
    
    
	int tmp = *q;
	*q = *p;
	*p = tmp;
}
//三数取中
int GetMidIndex(int* a, int begin, int end)
{
    
    
	int mid = (begin + end) / 2;
	if (a[begin] < a[mid])
	{
    
    
		if (a[mid] < a[end])
			return mid;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else // a[begin] > a[mid]
	{
    
    
		if (a[mid] > a[end])
			return mid;
		else if (a[begin] < a[end])
			return begin;
		else
			return end;
	}
}

The exchange function is used in most sorts, and it is more convenient to write a special exchange function.

Insertion sort

Idea: The basic operation of insertion sort is to insert a data into an ordered sequence that has already been sorted, so as to obtain a sequence that adds a new data;
Insert picture description here

// 插入排序
void InsertSort(int* a, int n)
{
    
    
	assert(a);
	for (int i = 0; i < n-1; i++)
	{
    
    
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
    
    
			if (tmp < a[end])
			{
    
    
				//a[end+1] = a[end];
				Swap(&a[end], &a[end + 1]);
				--end;
			}
			else
			{
    
    
				break;
			}
		}
		//a[end + 1] = tmp;
	}
	return a;
}

Hill sort

In Hill sorting, we first set an increment value, and then divide the data into several groups according to the increment (grouping is only a logical grouping, not a real grouping), and then sort the data in the group. After sorting, the increment becomes smaller, and then sorting is performed according to the increment. By analogy, when the increment is 1, when sorting is performed, the data at this time becomes relatively regular after the previous processing.
Insert picture description here

// 希尔排序
void ShellSort(int* a, int n)
{
    
    
	assert(a);
	int gap = n;
	while (gap > 1)
	{
    
    
	    //确保最后一次时gap为1;
	    //gap逐渐缩小;
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)
		{
    
    
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
    
    
				if (tmp < a[end])
				{
    
    
					//a[end+1] = a[end];
					Swap(&a[end], &a[end + gap]);
					end -= gap;
				}
				else
				{
    
    
					break;
				}
			}
			//a[end + 1] = tmp;
		}
	}
	return a;
}

Select sort

Selection sort is to find the smallest number in a set of data, exchange it with the first number, the first number becomes ordered, and then traverse from the second number to find the smallest number, and the first number Exchange the two numbers, and so on;
optimize it here: find the largest number and the smallest number at the same time, and put them in the last and first place, and so on;
Insert picture description here

//选择排序
void SelectSort(int* a, int n)
{
    
    
	assert(a);
	int end = n - 1, begin = 0;
	while (begin < end)
	{
    
    
		int min,max;//最大数和最小数的下标
		min = max = begin;
		//循环找到最大的数和最小的数
		for (int i = begin+1; i <= end; i++)
		{
    
    
			if (a[i] > a[max])
			{
    
    
				max = i;
			}
			if (a[i] < a[min])
			{
    
    
				min = i;
			}
		}
        
		Swap(&a[begin], &a[min]);
		//防止第一个元素为max,若第一个元素最大,此时min下标为第一个,先让max=min;
		if (begin == max)
		{
    
    
			max = min;
		}
		Swap(&a[end], &a[max]);
        //缩小范围
		begin++; end--;
	}
}

Bubble Sort

Compare adjacent elements in pairs, exchange them in reverse order, and exchange the largest number to the end in each pass;
Insert picture description here

//冒泡排序
void BubbleSort(int* a, int n)
{
    
    
	assert(a);
	for (int i = 0; i < n-1; i++)
	{
    
    
		for (int j = 0; j < n-i-1; j++)
		{
    
    
			if (a[j] > a[j + 1])
			{
    
    
				Swap(&a[j], &a[j + 1]);
			}
		}
	}
	return a;
}

zhi## There are three methods of quick sorting (three methods)
, all of which are to set a reference number, put the numbers larger than the reference number to the back, and put the numbers smaller than the reference number to the front, and then perform recursion to make Its order:
1. Left and right pointer method:
two pointers in front and one in the back. Right starts from the rear and left starts from the front. After left finds a value larger than key (key is the reference value), right goes forward to find the ratio If the key is small, the two numbers are exchanged, and so on. Finally, the key just falls to the final sorted position, and then recurses in the two intervals before and after the key;
Insert picture description here

// 快速排序左右指针法
int PartSort1(int* a, int left, int right)
{
    
    
	//int key = a[right];
	//三数取中,防止逆序时为时间复杂度最大;
	int midIndex = GetMidIndex(a, left, right);
	Swap(&a[midIndex], &a[right]);
	int keyi = right;
	while (right > left)
	{
    
    
		while (right > left && a[left] <= a[keyi])  left++;
		while (right > left && a[right] >= a[keyi])  right--;
		Swap(&a[right], &a[left]);
	}

	Swap(&a[keyi], &a[right]);
	return left;
}
void QuickSort1(int* a, int left, int right)
{
    
    
	assert(a);
	if (left >= right) return;
	
	int meet = PartSort1(a, left, right);
	QuickSort1(a, left, meet - 1);
	QuickSort1(a, meet + 1, right);
	return a;
}

Second, the digging method
first save the key, and use the key position as the pit position. Left first finds a number larger than the key and fills it in the key position. The left position becomes a pit, and right finds a better The key is a small number, and then fill in the pit, and so on, and finally the key just falls to the final sorted position, and then recursively in the two intervals before and after the key;
Insert picture description here

// 快速排序挖坑法
int PartSort2(int* a, int left, int right)
{
    
    
	int midIndex = GetMidIndex(a, left, right);
	Swap(&a[midIndex], &a[right]);

	int key = a[right];
	
	while (right > left)
	{
    
    
		while (right > left && a[left] <= key)  left++;
		a[right] = a[left];
		while (right > left && a[right] >= key)  right--;
		a[left] = a[right];
	}
	a[left] = key;
	return left;
}
void QuickSort2(int* a, int left, int right)
{
    
    
	assert(a);
	if (left >= right) return;

	int meet = PartSort2(a, left, right);
	QuickSort2(a, left, meet - 1);
	QuickSort2(a, meet + 1, right);
	return a;
}

3. Front and back pointer method
One front and one back pointer, the initial cur=0, prev=cur-1, cur is like a locomotive, pulling the number greater than the key value to the back;
Insert picture description here

// 快速排序前后指针法
int PartSort3(int* a, int left, int right)
{
    
    
	int midIndex = GetMidIndex(a, left, right);
	Swap(&a[midIndex], &a[right]);

	int prev = left - 1;
	int cur = left;
	int keyindex = right;

	while (cur < right)
	{
    
    
		if (a[cur] < a[keyindex] && ++prev != cur)
			Swap(&a[prev], &a[cur]);

		++cur;
	}

	Swap(&a[++prev], &a[keyindex]);

	return prev;
}
void QuickSort3(int* a, int left, int right)
{
    
    
	assert(a);
	if (left >= right) return;

	int meet = PartSort1(a, left, right);
	QuickSort3(a, left, meet - 1);
	QuickSort3(a, meet + 1, right);
	return a;
}

Merge sort

Recursive implementation:
Merge sorting is a sorting algorithm that uses the idea of ​​merging. This algorithm uses the classic divide and conquer strategy (divide and conquer method divides the problem into small problems and then solves it recursively, while the conquering stage will divide the results obtained in each stage The answer is'fix' together, that is, divide and conquer).
Insert picture description here

// 归并排序递归实现
void _MergeSort(int* a, int L,int R,int* tmp)
{
    
    
	if (L >= R)
		return;

	int M = (L + R) / 2;
	_MergeSort(a, L, M, tmp);
	_MergeSort(a, M + 1, R, tmp);

	int begin1 = L, end1 = M;
	int begin2 = M + 1, end2 = R;
	int i = L;
	while (begin1 <= end1 && begin2 <= end2)
	{
    
    
		if (a[begin1] > a[begin2])
			tmp[i++] = a[begin2++];
		else
			tmp[i++] = a[begin1++];
	}

	while (begin1 <= end1)
		tmp[i++] = a[begin1++];
	
	while (begin2 <= end2)
		tmp[i++] = a[begin2++];
	
	for (int i = L; i <= R; i++)
	{
    
    
		a[i] = tmp[i];
	}
}
void MergeSort(int* a, int n)
{
    
    
	assert(a);
	int* tmp = malloc(sizeof(int) * n);
	_MergeSort(a, 0, n - 1, tmp);
	return a;
	free(tmp);
}

// 归并排序非递归实现
void MergeArr(int* a, int begin1, int end1, int begin2, int end2, int* tmp)
{
    
    
	int left = begin1, right = end2;
	int index = begin1;
	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++];

	// 把归并好的再tmp的数据在拷贝回到原数组
	for (int i = left; i <= right; ++i)
		a[i] = tmp[i];
}
void MergeSortNonR(int* a, int n)
{
    
    
	assert(a);
	int* tmp = malloc(sizeof(int) * n);
	int gap = 1;
	while (gap < n)
	{
    
    
		for (int i = 0; i < n; i += 2 * gap)
		{
    
    
			// [i,i+gap-1] [i+gap, i+2*gap-1]
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			// 1、合并时只有第一组,第二组不存在,就不需要合并
			if (begin2 >= n)
				break;

			// 2、合并时第二组只有部分数据,需要修正end2边界
			if (end2 >= n)
				end2 = n - 1;

			MergeArr(a, begin1, end1, begin2, end2, tmp);
		}
		//PrintArray(a, n);
		gap *= 2;
	}
	free(tmp);
}

Guess you like

Origin blog.csdn.net/qq_43745617/article/details/113251312