分治策略,递归,快排


问题不变,规模变小
在这里插入图片描述

将循环函数改为递归

计算阶乘

int fun(int n)
{
	int sum = 1;
	for (int i = 1; i <= n; ++i)
	{//for(int i=1; ;++i)程序不会崩溃
		sum = sum * i;
	}
	return sum;
}
//O(n) S(1)
int fac(int n)
{
	if (n <= 1) return 1;
	else
	{
		return fac(n - 1) * n;
	}
}
//O(N) S(n)

2,打印一位数组

在这里插入图片描述

//所有的n都为0,打印结果为12,12,12
void Print(const int* br, int &n)
{
	if (n > 0)
	{//所有的n都为0,打印结果为12,12,12
		Print(br, --n);
		cout << br[n] << " ";
	}
}
void Print(const int* br, int n)
{
	if (n > 0)
	{
		Print(br, --n);
		//cout << br[n-1] << " ";将出错打印结果为23,34; 
		cout << br[n] << " ";
	}
}
//这样导致栈溢出(无穷递归,将栈帧冲爆)
void Print(const int* br, int n)
{
	if (n > 0)
	{
		Print(br, n--);
		cout << br[n -1] << " ";
	}
}
//可以成功
void Print(const int* br, int n)
{
	if(n>0)
	{
		Print(br,n-1);//在回归中完成
		cout << br[n-1] << " ";
		/*
		在递推中完成
		cout << br[n-1] << " ";	
        Print(br,n-1);
		*/
	}
}
void Print_fac(const int* br, int n)
{
	if (br == NULL || n < 1) return;
	Print(br, n);
	cout << endl;
}
void Print_Ar(const int* br, int n)
{
	for (int i = 0; i < n; ++i)
	{
		cout << br[i] << " ";
	}
	cout << endl;
}
int main()
{
	int ar[] = { 12,23,34 };
	int n = sizeof(ar) / sizeof(ar[0]);
	Print_Ar(ar, n);
	Print_fac(ar, n);
	return 0;
}

查询一个数组里面的值的下标,若果没有改值则输出-1

int Find(int* ar, int n, int val)
{
	if (n ==0||ar[n-1]==val) return n-1;
	else
	{
			return Find(ar,n - 1,val);
	}

}
int Find_fac_pos(int* ar, int n, int val)
{
	if (ar == NULL || n < 1) return -1;
	Find(ar, n, val);
}
int FindPos(int* ar, int n, int val)
{
	if (ar == NULL || n < 1) return -1;
	int pos = n - 1;
	while (pos >= 0 && ar[pos] != val)
	{
		--pos;
	}
	return pos;
}
int main()
{
	int ar[] = { 12,23,34,45 };
	int n = sizeof(ar) / sizeof(ar[0]);
	int val = 100;
	int pos = FindPos(ar, n, val);
	cout << pos << endl;
	int m=Find_fac_pos(ar,  n, val);
	cout << m <<endl;
	return 0;
}

在这里插入图片描述

如果有返回值,必须每一次递归都返回将改值传达给第一次递归,如果某一次递归没有返回值,就会随着函数的结束,栈帧被清理挥手上一次返回的数据也被清除

快排(递归)

快排图解

每一次将一组数据的left作为tmp,将数据划分为两部分,左边全部小于tem,右边全部大于tmp,然后左右两边成为新的两组数据,继续以相同的方式排序;直至每组数据为一个数
在这里插入图片描述
在这里插入图片描述

1,快排的代码

//划分函数,将该组数据分为两部分左边小于初始数据的第一个值即tmp,右边数据全部大于tmp
int Parition(int* br, int left, int right)
{
	int tmp = br[left];
	while (left < right)
	{
	  while (left < right&&br[right]>tmp)
	  {
		--right;
	  }
	  if (left < right) br[left] = br[right];
	  while (left < right && br[left] <= tmp)
	  {
		++left;
	  }
	  if (left < right) br[right] = br[left];
	}
	br[left] = tmp;
	return left;
}
void  PassQuick(int* br, int left, int right)
{
	if (left < right)//if(left<=right)left<gight说明至少每部分有两个元素
	{
		int pos = Parition(br, left, right);
		PassQuick(br, left, pos-1);
		PassQuick(br, pos+1, right);
	}
}
void QuickSort(int* br, int n)
{
	if (br == NULL || n < 2) return;
	PassQuick(br, 0, n - 1);
}
void Printf_Ar(int* ar, int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << ar[i] << " ";
	}
	cout << endl;
}
int main()
{
	int ar[] = { 56,12,78,90,34,23,100,56,45,67,89 };
	int n = sizeof(ar) / sizeof(ar[0]);
	Printf_Ar(ar, n);
	QuickSort(ar, n);
	Printf_Ar(ar, n);
	return 0;
}

2,快排的问题

1,快排的最好最差效率

** 如果快排本身就是有序的那么快排的效率就会很低(原因:一个完全有序为例:每次分出去的两个部分其中一份只有一个数据时间复杂度为n2);时间复杂程度就为N2 理想情况为log 2 n(每次都是一半划分)**

2,将递归改为非递归

利用栈或者队列来处理

#include<stack>//栈
#include<queue>//队列
using namespace std;

//划分函数,将该组数据分为两部分左边小于初始数据的第一个值即tmp,右边数据全部大于tmp
int Parition(int* br, int left, int right)
{
	int tmp = br[left];
	while (left < right)
	{
	  while (left < right&&br[right]>tmp)
	  {
		--right;
	  }
	  if (left < right) br[left] = br[right];
	  while (left < right && br[left] <= tmp)
	  {
		++left;
	  }
	  if (left < right) br[right] = br[left];
	}
	br[left] = tmp;
	return left;
}

void QuickSort(int* br, int n)
{
	if (br == NULL || n < 2) return;
	queue<int>qu;
	qu.push(0);
	qu.push(n - 1);
	while (!qu.empty())
	{
		int left = qu.front(); qu.pop();
		int right = qu.front(); qu.pop();
		int pos = Parition(br, left, right);
		if (left < pos - 1)
		{
			qu.push(left);
			qu.push(pos - 1);
		}
		if (pos + 1 < right)
		{
			qu.push(pos + 1);
			qu.push(right);
		}
	}
}
void Printf_Ar(int* ar, int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << ar[i] << " ";
	}
	cout << endl;
}
int main()
{
	int ar[] = { 56,12,78,90,34,23,100,56,45,67,89 };
	int n = sizeof(ar) / sizeof(ar[0]);
	Printf_Ar(ar, n);
	QuickSort(ar, n);
	Printf_Ar(ar, n);
	return 0;
}
#include<stack>//栈
#include<queue>//队列
using namespace std;

//划分函数,将该组数据分为两部分左边小于初始数据的第一个值即tmp,右边数据全部大于tmp
int Parition(int* br, int left, int right)
{
	int tmp = br[left];
	while (left < right)
	{
	  while (left < right&&br[right]>tmp)
	  {
		--right;
	  }
	  if (left < right) br[left] = br[right];
	  while (left < right && br[left] <= tmp)
	  {
		++left;
	  }
	  if (left < right) br[right] = br[left];
	}
	br[left] = tmp;
	return left;
}

void QuickSort(int* br, int n)
{
	if (br == NULL || n < 2) return;
	queue<std::pair<int,int>>qu;
	qu.push(std::pair<int,int>(0,n-1));
	while (!qu.empty())
	{
		std::pair<int, int>pos = qu.front(); qu.pop();
		int mid = Parition(br, pos.first, pos.second);
		if (pos.first<mid- 1)
		{
			qu.push(std::pair<int, int>(pos.first, mid - 1));
		}
		if (mid+ 1 < pos.second)
		{
			qu.push(std::pair<int,int>(mid+1,pos.second));
		}
	}
}
void Printf_Ar(int* ar, int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << ar[i] << " ";
	}
	cout << endl;
}
int main()
{
	int ar[] = { 56,12,78,90,34,23,100,56,45,67,89 };
	int n = sizeof(ar) / sizeof(ar[0]);
	Printf_Ar(ar, n);
	QuickSort(ar, n);
	Printf_Ar(ar, n);
	return 0;
}
3,现在的递归是从两边向中间递归的,能否改为从一边递归

(单链表没有Prev如果要用递归就要这要改)
快排 归并,堆排

时间复杂度
空间复杂度
稳定与否
什么情况下需要稳定的排序什么情况下需要不稳定的排序
什么其工况下程序会退化,什么情况下选择快排,什么情况下选择归并排序,什么情况下选择堆排序
能否将你的递归排序写成非递归排序

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值