排序详解-第二篇 快速排序 归并排序

1.快速排序

        首选选择一个key值,一般选择数组中第一个作为key值,再定义两个变量L,R。R从右向左找比key小的值,L从左到右找比key大的值,都找到后,进行交换。当L和R相遇后,将此位置的的数与key值交换。然后再把key值左边的区间和右边的区间重复上述步骤。

hoare版本:

void quicksort(int* a, int left,int right)//简单版快排
{

	if (left >= right)
	{
		return; 
	}


	int key = left;
	int begin = left;
	int end = right;

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

		swap(a[begin], a[end]);

	}
	 
	swap(a[key], a[begin]);
	key = begin;

	quicksort(a, left, key-1);
	quicksort(a, key+1, right);

}

缺点:

当数组有序时,可能会引起栈溢出,会退化为O(N^2{})的时间复杂度

解决方法:

1.三数取中(最左侧的数,最右侧的书,中间的数)取这三个数大小为中间的值作为key值
//三数取中
void quicksort(int* a, int left,int right)//简单版快排
{

	if (left >= right)
	{
		return; 
	}

	int mid = getmidnum(a, left, right);
	swap(a[left], a[mid]);

	int key = left;
	int begin = left;
	int end = right;

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

		swap(a[begin], a[end]);

	}
	 
	swap(a[key], a[begin]);
	key = begin;

	quicksort(a, left, key-1);
	quicksort(a, key+1, right);

}


int getmidnum(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 right;
		}
		else
		{
			return left;
		}
	}
	else
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}

}
2.小区间优化
void Insertsort(int* a, int n)
{

	for (int i = 0; i + 1 < n; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}

}

int getmidnum(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 right;
		}
		else
		{
			return left;
		}
	}
	else
	{
		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; 
	}

	if (right - left+1 < 10)//小区间优化,减少递归次数
	{

		Insertsort(a + left, right - left + 1);

	}
	else
	{
		int mid = getmidnum(a, left, right);//三数取中
		swap(a[left], a[mid]);

		int key = left;
		int begin = left;
		int end = right;

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

			swap(a[begin], a[end]);

		}

		swap(a[key], a[begin]);
		key = begin;

		quicksort(a, left, key - 1);
		quicksort(a, key + 1, right);
	}

	

}


非递归写法:(使用栈)

int getmidnum(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 right;
		}
		else
		{
			return left;
		}
	}
	else
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}

}


int part1sort(int* a, int left, int right)//快排模板
{
	int mid = getmidnum(a, left, right);
	swap(a[left], a[mid]);

	int key = left;
	int begin = left;
	int end = right;

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

		swap(a[begin], a[end]);

	}

	swap(a[key], a[begin]);

	return begin;
}



void quicksortNonR(int* a, int left, int right)//非递归快排
{
	stack<int>st;
	st.push(right);
	st.push(left);

	while (st.size())
	{

		int begin = st.top();
		st.pop();
		int end = st.top();
		st.pop();

		int key = part1sort(a, begin, end);


		if (key + 1 < end)
		{
			st.push(end);
			st.push(key + 1);

		}

		if (begin < key - 1)
		{
			st.push(key - 1);
			st.push(begin);
		}

	}

}

归并排序:
 



void _guisort(int* a, int* tmp, int begin, int end)
{

	if (begin >= end)
	{
		return;
	}

	int mid = (begin + end) / 2;

	_guisort(a, tmp, begin, mid);
	_guisort(a, tmp, mid+1, end);

	int begin1 = begin, end1 = mid;
	int begin2 = mid+1, end2 = end;


	int i = begin;

	while (begin1 <= end1 && begin2 <= end2)
	{

		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}

	}

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}

	memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));

}


void guisort(int* a, int n)
{

	int* temp = (int*)malloc(sizeof(int) * n);

	_guisort(a, temp, 0, n - 1);

}

非递归归并排序:


void guisortNonr(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);

	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;

			if (begin2 >=n)
			{
				break;
			}

			if (end2 >= n)
			{
				end2 = n - 1;
			}

			int j = i;

			while (begin1 <= end1 && begin2 <= end2)
			{

				if (a[begin1] < a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}

			}

			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
			memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));

		}

		gap = gap * 2;

	}


}


本篇完

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值