排序算法总结

快速排序霍尔算法

void QuickSort(int* arr, int begin,int end) {
	if (begin >= end)
		return;
	int keyi = begin;
	int right = end;
	int left = begin;
	while (right > left) {
		
		//此时不能先走左边,应为先走左边会是右边找到的不一定是小值,即两指针相遇在一个大于keyi值的地方

		//先走右边即一定能确保相遇的地方一定是小于keyi值的地方
		while (right > left && arr[keyi] <= arr[right]) {
			right--;
		}
		while (right > left && arr[keyi]>=arr[left]) {
			left++;
		}
		
		swap(arr + left, arr + right);
	}
	swap(arr + left, arr+keyi);
	QuickSort(arr, begin, left - 1);
	QuickSort(arr, left+1,end);
}

      右边指针一定要先走,才能确保最后被交换过去的是比a[left]小的值

while (right > left && arr[keyi] <= arr[right]) {
            right--;
        }

这段代码前面语句一定要注意,防止在找的过程中两个指针交叉。

后面语句一定要注意等号,防止指针一直停在那里发生死循环。

快速排序挖坑法

// 快速排序挖坑法
void  QuickSort2(int* a, int left, int right) {
	if (left >= right)
		return;
	int begin = left;
	int end = right;
	int key = a[left];
	int holei = left;
	while (right > left) {

		while (right > left && a[right] >= key) {
			right--;
		}
		a[holei] = a[right];
		holei = right;
		

		while (right > left && a[left] <= key) {
			left++;
		}
		
		a[holei] = a[left];
		holei = left;
		
	}
	a[left] = key;
	QuickSort2(a,begin,left-1);
	QuickSort2(a, left + 1, end);
}

将要排序的第一个元素设为key,且将第一个元素下标设为坑

右边找比key值小的数,找到之后将a[right]填入坑中,在将right设为坑

最后两个指针相遇,将key值填入坑中,即完成左右两端的排序

快速排序两指针法

// 快速排序前后指针法
void QuickSort(int* a, int left, int right) {
	if (right <= left)
		return;
	int begin = left;
	int end = right;
	int keyi = left;
	int prev = left, cur = left + 1;
	while (cur <= right) {
		while (a[cur] >= a[keyi] && cur <= right) {
			cur++;
		}
		if (cur <= right) {
			prev++;
			int temp;
			temp = a[prev];
			a[prev] = a[cur];
			a[cur] = temp;
		}
		cur++;
	}
	int temp;
	temp = a[prev];
	a[prev] = a[keyi];
	a[keyi] = temp;
	QuickSort(a, begin, prev - 1);
	QuickSort(a, prev + 1, end);

}

保存left为keyi,a[left]设为prev,a[left+1]设为cur,cur找比keyi元素值小的数字,找到后prev++

然后交换a[prev]和a[cur],cur再++,加  if (cur <= right) 是因为cur在上面循环已经越界了,后面的a[prev]被赋值了,就造成了越界最后再将prev停的值与keyi的值交换,保证了prev前面均是小于a[keyi]的值

快速排序非递归实现

// 快速排序 非递归实现
void QuickSortNonR(int* a, int left, int right) {
	Stack st;
	StackInit(&st);
	StackPush(&st, left);
	StackPush(&st, right);
	while (isStackEmpty(&st)) {
		int end = StackTop(&st);
		StackPop(&st);
		int begin = StackTop(&st);
		StackPop(&st);
		int keyi = begin;
		int prev = begin, cur = begin + 1;
		while (cur <= right) {
			while (a[cur] >= a[keyi] && cur <= right) {
				cur++;
			}
			if (cur <= right) {
				prev++;
				int temp;
				temp = a[prev];
				a[prev] = a[cur];
				a[cur] = temp;
			}
			cur++;
		}
		int temp;
		temp = a[prev];
		a[prev] = a[keyi];
		a[keyi] = temp;

		if (end > prev + 1) {
			StackPush(&st, prev + 1);
			StackPush(&st, end);
		}
		if (prev - 1 > begin) {
			StackPush(&st, begin);
			StackPush(&st, prev - 1);
		}
	}

}

先创建一个栈,将两个区间入栈,将栈顶元素赋值给left,right,注意赋值一个出一个。

while循环判断为空就结束。

只要区间还>=1就继续入栈。

归并排序递归

void _MergeSort(int* a, int* temp, int left, int right) {
	if (right <= left)
		return;
	int mid = (right + left) / 2;
	

	_MergeSort(a, temp, left, mid);
	
	_MergeSort(a, temp, mid + 1, right);


	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = left;
	while (begin1 <= end1 && begin2 <= end2) {
		if (a[begin1] <= a[begin2]) {
			temp[index++] = a[begin1++];
		}
		else {
			temp[index++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
		temp[index++] = a[begin1++];
	while (begin2 <= end2)
		temp[index++] = a[begin2++];
	memcpy(a + left, temp + left, sizeof(int) * (right - left + 1));
}
// 归并排序递归实现
void MergeSort(int* a, int n) {
	int* temp = (int*)malloc(sizeof(int) * n);
	assert(temp);
	_MergeSort(a, temp, 0, n - 1);
	/*for (int i = 0; i < n; i++) {
		a[i] = temp[i];
	}*/
	free(temp);
}

类似与二叉树前序遍历,两个数为一个区间等价与一个节点。

归并排序非递归


// 归并排序非递归实现
void MergeSortNonR(int* a, int n) {

	int* temp = (int*)malloc(sizeof(int) * n);
	assert(temp);
	int gap = 1;
	while (gap < n) {
		for (int i = 0; i < n; i += 2 * gap) {
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			int index = i;
			if (end1 >= n)
				break;
			if (end2 >= n)
				end2 = n - 1;
			while (begin1 <= end1 && begin2 <= end2) {
				if (a[begin1] <= a[begin2]) {
					temp[index++] = a[begin1++];
				}
				else {
					temp[index++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
				temp[index++] = a[begin1++];
			while (begin2 <= end2)
				temp[index++] = a[begin2++];
			memcpy(a + i, temp + i, sizeof(int) * (gap - i) * 2);
		}

		gap = gap * 2;
	}
	free(temp);
}

最外层while控制排序最小区间大小,fro循环控制将区间大小一个等级的排序

如果begin2越界了,则不需要排序,直接拷贝回去。如果end2越界则修改end2到数组最后一个值

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值