七种基本排序思考


//插排
//稳定
//时间复杂度【最差情况】:O(n^2)
//空间复杂度:O(1)
void InsertSort(int array[], int size)
{
	int key;
	int i, j;
	for (i = 1; i < size; i++){
		key = array[i];
		for (j = i - 1; j >= 0; j--){
			if (key >= array[j]){
				break;
			}
			else{
				array[j + 1] = array[j];
			}
		}
		array[j + 1] = key;
	}
}

void _InsertSort(int array[], int size, int gap)
{
	for (int g = 0; g < gap; g++){
		int key;
		int i, j;
		for (i = gap + g; i < size; i += gap){
			key = array[i];
			for (j = i - gap; j >= 0; j -= gap){
				if (key >= array[j]){
					break;
				}
				else{
					array[j + gap] = array[j];
				}
			}
			array[j + gap] = key;
		}
	}
}

//希排
//1 不稳定
//2 时间复杂度【最差情况】: O(n^2)
void ShellSort(int array[], int size)
{
	int gap = size;
	while (1){
		gap = gap / 3 + 1;
		_InsertSort(array, size, gap);
		if (gap == 1){
			break;
		}
	}
}

void Swap(int *a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

//不稳定
//时间复杂度   O(n^2)
//选择排序1(每次选择最大的放到最后)
void SelectSort(int array[], int size)
{
	//i代表每次还剩多少个数,当剩下一个数的时候,就不要移动了
	for (int i = size; i > 1; i--){
		int max = 0;//最大值下标
		for (int j = 1; j < i; j++){
			if (array[j] > array[max]){
				max = j;
			}
		}
		Swap(array + max, array + i - 1);
	}
}

//选择排序2(每次选择最大的放到最后,同时选择最小的放到最前边)
void SelectSrotOP(int array[], int size)
{
	int left = 0, right = size - 1;
	while (left < right)
	{
		int min = left, max = left;
		for (int j = left + 1; j <= right; j++){
			if (array[j] > array[max]){
				max = j;
			}
			if (array[j] < array[min]){
				min = j;
			}
		}
		Swap(array + left, array + min);
		//注意!!!
		if (max == left){//此时说明最大值下标就是left下标元素
			max = min;//此时最大值已经被交换到下标为min了,所以max应该移到min处
		}
		Swap(array + right, array + max);
		left++; right--;
	}
}

void AdjustDown(int array[], int size, int root)
{
	int left = 2 * root + 1;//左孩子下标
	int right = 2 * root + 2;//右孩子下标

	if (left >= size){
		return;//没有左孩子(右孩子也肯定没有)
	}

	int max = left;
	if (right < size && array[right] > array[left]){
		max = right;
	}//有孩子,判断大孩子下标

	if (array[root] >= array[max]){
		return;//如果双亲节点大于大孩子,不用调整
	}

	Swap(array + root, array + max);//交换大孩子和双亲节点
	AdjustDown(array, size, max);
}


void CreateHeap(int array[], int size)
{
	//从最后一个非叶子节点
	//不断向下调整
	for (int i = (size - 1) / 2; i >= 0; i--){
		AdjustDown(array, size, i);
	}
}

//堆排
//不稳定
//时间复杂度 O(N*logN)
void HeapSort(int array[], int size)
{
	//1 建大堆(升序)(找最大值)
	CreateHeap(array, size);

	for (int i = 0; i < size - 1; i++){
		Swap(&array[0], &array[size - 1 - i]);
		AdjustDown(array, size - i - 1, 0);
	}
}

//冒泡排序
//稳定
//时间复杂度 O(N^2)
void BubbleSort(int array[], int size)
{
	for (int i = 0; i < size - 1; i++){
		int isSorted = 1;
		for (int j = 0; j < size - 1 - i; j++){
			if (array[j] > array[j + 1]){
				Swap(array + j, array + j + 1);
				isSorted = 0;
			}
		}
		if (1 == isSorted){
			break;
		}
	}
}

//快排小的放左、大的放右【左右指针法】
//时间复杂度 O(N)
int Partition_01(int array[], int left, int right)//基准值的下标
{
	int begin = left;//不是0
	int end = right; //不是right-1

	while (begin < end){
		//如果基准值在最右边,先动begin
		while (begin < end && array[begin] <= array[right]){
			begin++;//第二次比较左右下标,防止所有元素都小于基准值,
		}
		while (begin < end && array[end] >= array[right]){
			end--;//第二次比较左右下标,防止所有元素都大于基准值,
		}
		Swap(array + begin, array + end);
	}
	Swap(array + begin, array + right);

	return begin;//基准值
}

//快排
//时间复杂度 O(N*logN)   最坏情况就是单枝树O(N^2)
//空间复杂度 O(logN)      O(N)
//array [left, right]
//左闭右闭
void _QuickSort(int array[], int left, int right)
{
	if (left >= right){
		return;
	}

	int div = Partition_02(array, left, right);//基准值的下标
	
	_QuickSort(array, left, div - 1);  //[left, div-1]
	_QuickSort(array, div + 1, right); //[div+1, right]
}

void  QuickSort(int array[], int size)
{
	_QuickSort(array, 0, size - 1);
}

//快排小的放左、大的放右【左右挖坑法】
//时间复杂度 O(N)
int Partition_02(int array[], int left, int right)
{
	int begin = left;
	int end = right;
	int pivot = array[right];//pivot 存的就是基准值

	while (begin < end){
		while (begin < end && array[begin] <= pivot){
			begin++;
		}
		array[end] = array[begin];//补右坑==挖左坑
		while (begin < end && array[end] >= pivot){
			end--;
		}
		array[begin] = array[end];//补左坑==挖右坑
	}
	array[begin] = pivot;

	return begin;
}

//快排
//时间复杂度 O(N*logN)   最坏情况就是单枝树O(N^2)
//空间复杂度 O(logN)      O(N)
//array [left, right]
//左闭右闭
void _QuickSort(int array[], int left, int right)
{
	if (left >= right){
		return;
	}

	int div = Partition_02(array, left, right);//基准值的下标
	
	_QuickSort(array, left, div - 1);  //[left, div-1]
	_QuickSort(array, div + 1, right); //[div+1, right]
}

void  QuickSort(int array[], int size)
{
	_QuickSort(array, 0, size - 1);
}

//快排小的放左、大的放右【前后指针】
//时间复杂度 O(N)
int Partition_03(int array[], int left, int right)
{
	int div = left;
	int cur = left;

	while (cur < right){
		if (array[cur] < array[right]){
			Swap(array + cur, array + div);
			div++;
		}
		cur++;
	}

	Swap(array + div, array + right);
	return div;
}

//快排
//时间复杂度 O(N*logN)   最坏情况就是单枝树O(N^2)
//空间复杂度 O(logN)      O(N)
//array [left, right]
//左闭右闭
void _QuickSort(int array[], int left, int right)
{
	if (left >= right){
		return;
	}

	int div = Partition_03(array, left, right);//基准值的下标
	
	_QuickSort(array, left, div - 1);  //[left, div-1]
	_QuickSort(array, div + 1, right); //[div+1, right]
}

void  QuickSort(int array[], int size)
{
	_QuickSort(array, 0, size - 1);
}

附加讲解:(快排不稳定)

选择基准值的方法:1)最边上(最左、最右)

                                 2)随机

                                 3)三数取中


void Merge(int array[], int left, int mid, int right, int *extra)
{
	int left_i = left;
	int right_i = mid;
	int extra_i = left;

	while (left_i < mid && right_i < right){
		if (array[left_i] <= array[right_i]){
			extra[extra_i++] = array[left_i++];
		}
		else{
			extra[extra_i++] = array[right_i++];
		}
	}

	while (left_i < mid){
		extra[extra_i++] = array[left_i++];
	}

	while (right_i < right){
		extra[extra_i++] = array[right_i++];
	}

	for (int i = left; i < right; i++){
		array[i] = extra[i];
	}
}

//归并排序
//时间复杂度 O(N*logN)  
//空间复杂度 O(N)       
//array [left, right)
//左闭右开
void _MergeSort(int array[], int left, int right, int *extra)
{
	if (left == right - 1){
		return;//[0,1)
	}
	if (left >= right){
		return;//区间没有数了
	}

	int mid = left + (right - left) / 2;
	_MergeSort(array, left, mid, extra);//[left, mid)//左边排有序
	_MergeSort(array, mid, right, extra);//[mid,  right)//右边排有序
	Merge(array, left, mid, right, extra);//整体合并成有序
}

void  MergeSort(int array[], int size)
{
	int *extra = (int *)malloc(size * sizeof(int));
	_MergeSort(array, 0, size, extra);//左闭右开
	free(extra);
}

归排稳定


总结:

猜你喜欢

转载自blog.csdn.net/qq_42080151/article/details/84453014
今日推荐