快速排序和归并排序的不同种实现

1.快速排序 :核心思想:选出一个key当作基准元素,让数组左边是比key小的元素,右边是比key大的元素。

实现:

int PartSort(int * a,int left,int right)
{
	 int key = left;
	//int key = GetMidIndex(a, left, right);
	int s = a[key];
	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[left], &a[key]);
	return left;
}
  void QuikeSort(int *a,int left, int right){
	if (left >= right)return;
	int key = PartSort(a, left, right);
	QuikeSort(a, left, key - 1);
	QuikeSort(a, key + 1, right);
}
  //hoare版本

当选取区间左边元素作为key元素时,当数组有序时或者接近有序时时间杂度为O(N*N)

对次我们经行一个优化:3数取中。

//3数取中,避免顺序快排出现时间复杂度为O(n*n);
  int  GetMidIndex(int* a, int left, int right)
  {
	  int mid = (left + right) / 2;
	  if (a[left] > a[mid])
	  {
		  if (a[right] > a[left])
			  return  left;
		  else if (a[right] < a[mid])
			  return mid;
		  else
			  return right;
	  }
	  else //a[left]<a[mid]
	  {
		  
		  if (a[right] > a[mid])return mid;
		  else if (a[left] > a[right]) return left;
		  else return right;
	  }

  }

注意此时不能只修改原代码中的key,因为原代码选左边做key 右边先走才保证了俩个指针相遇时的元素比key小 ,修改后的part函数如下

 
int PartSort(int * a,int left,int right)
{
	 int begin = left;
      
	 int key = GetMidIndex(a, left, right);
	int s = a[key];
	swap(&a[left],&a[key]);
	while (left < right)
	{
		while (left < right && a[right] >=s)
			--right;
		while (left < right && a[left]<=s)
			left++;
		swap(&a[left], &a[right]);
	}
	swap(&a[left], &a[begin]);
	return left;

另外的是实现方式:

//挖坑法快速排序
  int PartSort2(int* a, int left, int right)
  {
	  int hole = a[left];//挖坑
	 // int hole = a[GetMidIndex(a, left, right)];
		  int space = left;
	//  int  space = GetMidIndex(a, left, right);
	  while (left < right)
	  {
		  while (left < right && a[right] >= hole)
		  {
			  right--;
		  }
		  a[space] = a[right];
		  space = right;
		  while (left < right && a[left] <= hole)
		  {
			  left++;
		  }
		  a[space] = a[left];
		  space = left;
	  }
	  a[space] = hole;
	  return space;

  }
  void QuikeSort2(int* a, int left, int right)
  {
	  if (left >= right)return;
  int key = PartSort2(a, left, right);
  QuikeSort2(a, left, key - 1);
  QuikeSort2(a, key + 1, right);
  }
//非递归实现快速排序
  void QuikeSort3(int* a, int left, int right)
  {
	  ST st;
	  StackInit(&st);
	  StackPush(&st, left);
	  StackPush(&st, right);
	  while (!Stackempty(&st))
	  {
		  int _right = Stacktop(&st);
		  StackPop(&st);
		  int _left = Stacktop(&st);
		  StackPop(&st);
		  int key= PartSort(a, _left, _right);
		  if (_left < key - 1)
		  {
			  StackPush(&st, _left);
			  StackPush(&st, key - 1);
		  }
		  if (key + 1 < _right)
		  {
			  StackPush(&st, key + 1);
			  StackPush(&st, _right);
		  }
	  }
	  StackDestory(&st);
  }
//前后指针法
  int PartSort4(int *a,int left,int right)
  {
	  int mid = GetMidIndex(a, left, right);
	  swap(&a[left], &a[mid]);
	  int cur = left;
	  int prev = left + 1;
	  while (prev<= right)
	  {
		  if (a[prev] < a[left] && a[++cur] != a[prev])
			  swap(&a[prev], &a[cur]);
		  ++prev;
		 // while(prev<=right&&a[prev] > a[left])prev++;
		  //cur++;
		//  swap(&a[cur], &a[prev]);
		//  prev++;
	   }
	  swap(&a[left], &a[cur]);
	  return  cur;
  }
  void QuikeSort4(int* a, int left, int right)
  {
	  if (left >= right)return;
	  int key = PartSort4(a, left, right);
	  QuikeSort4(a, left, key - 1);
	  QuikeSort4(a, key + 1, right);
  }
 //小区间优化
  void QuikeSort5(int* a, int left, int right)
  {
	  if (right - left + 1 <= 10)
	  {
		  InsertSort(a + left, right - left + 1);
	  }//子问题是这一类问题时按照这样的方式处理,注意是类,将子问题按照类来划分;
	  else {
		  int key = PartSort4(a, left, right);
		  QuikeSort2(a, left, key - 1);
		  QuikeSort2(a, key + 1, right);
	  }
  }

归并排序:核心思想:分治 

实现:

/归并排序,递归版本时间复杂度n*logn;
  //递归的部分排序
 //对子问题经行归并排序
  void MergeSort(int* a, int begin, int end)
  {
	  int* temp = (int*)malloc(sizeof(int) * (end - begin + 1));
	  _MergeSort(a, begin, end, temp);
  }
  void _MergeSort(int* a, int begin, int end, int* temp)
  {
	  if (begin >= end)return;
	  int mid = begin + (end - begin) / 2;
	  //不能用mid-1否则会出现死循环,比如0,1。
	  _MergeSort(a, begin, mid, temp);
	  _MergeSort(a, mid + 1, end, temp);
	  //对子问题进行归并
	  int begin1 = begin; int end1 = mid;
	  int begin2 = mid + 1; int end2 = end;
	  int q = begin;
	  while (begin1 <= end1 && begin2 <= end2)
	  {
		  if (a[begin1] < a[begin2])
			  temp[q++] = a[begin1++];
		  else
			  temp[q++] = a[begin2++];
	  }
	  if (begin1 <= end1)
	  {
		  while (begin1 <= end1)
			  temp[q++] = a[begin1++];
	  }
	  if (begin2 <= end2)
	  {
            while (begin2 <= end2)
          temp[q++] = a[begin2++];
       }
	  memcpy(a + begin, temp+begin, sizeof(int)*(end - begin + 1));
  }
  
  //由于是归并所以得额外开数组避免原数组被覆盖;
  // 非递归实现归并排序;
  //从左到右 区间长度为1的俩俩归并,区间长度为2的俩俩归并..区间为4的俩俩归并..最后归并完成;
  void UnMergeSort(int* a, int begin, int end,int *temp)
  {
	  int gap = 1;
	  int i = 1;
	  for (gap = 1; gap <end - begin+1; gap = gap * 2)
	  {
		  for (i = 0; i <= end; i = i += 2 * gap)
		  {

			  int begin1 = i; int end1 = i + gap - 1;
			  if (end1 > end)end1 = end;
			  int begin2 = end1 + 1; int end2 = begin2 + gap - 1;
			  if (begin2 > end) {
				  begin2 = 1;
				  end2 = 0;
				  //不存在下一个区间
			  }
			  if (end2 > end)end2 = end;
			  //归并
			  int q = begin1;
			  int left1 = begin1; int right1 = end1;
			  int left2 = begin2; int right2 = end2;
			  while (left1 <= right1 && left2 <= right2)
			  {
				  if (a[left1] < a[left2])
					  temp[q++] = a[left1++];
				  else
					  temp[q++] = a[left2++];
			  }
			  if (left1 <= right1)
			  {
				  while (left1 <= right1)
					  temp[q++] = a[left1++];
			  }
			  if (left2 <= right2)
			  {
				  while (left2 <= right2)
					  temp[q++] = a[left2++];
			  }
			  memcpy(a + begin1, temp + begin1, sizeof(int) * (q - begin1));
		  }
	  }
  }

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值