文章目录
问题不变,规模变小
将循环函数改为递归
计算阶乘
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如果要用递归就要这要改)
快排 归并,堆排
时间复杂度
空间复杂度
稳定与否
什么情况下需要稳定的排序什么情况下需要不稳定的排序
什么其工况下程序会退化,什么情况下选择快排,什么情况下选择归并排序,什么情况下选择堆排序
能否将你的递归排序写成非递归排序