十步法将递归程序快速转变成迭代或循环程序

将递归程序转变为迭代程序的方法 在面试中,我们经常会被要求写一段程序解决某一个问题或提供某个功能,当我们写出用递归给出解法后,面试官往往会问有没有迭代的解法,这个时候面试者经常是束手无措,因为老实说迭代的解法是比较难相处的,所以本文就提供将递归程序转变为迭代程序的通用方法。 阅读详情

             前言:在有些情况下,我们更倾向于使用递归函数,如排序(合并排序)或树相关操作的算法(heapify/ heapify)。但是,递归函数在某些环境中,如在Visual C ++中,如果调用层次过深,可能会出现如堆栈溢出。许多专业的开发人员可能已经知道如何更改递归功能用迭代函数或使用栈(堆栈)和while循环解决(模拟递归的过程)堆栈溢出问题。

        如果您使用的是递归函数,因为你不控制调用堆栈和堆栈大小的限制,当递归调用的深度过深stackoverflow/heap-corruption可能随时发生。如果是换成迭代函数,这个过程还是比较复杂的。但是,为了做到这一点,这里介绍一个十步法将递归程序变换成迭代形式的程序。从而取代使用递归函数的栈,以避免堆栈溢出。下面依次介绍这十条规则。

           

 规则一:1.定义一个结构体,这里取名为:Snapshot.这个结构体主要是用来保存递归程序中每一步用到的数据。

                  2.该结构体Snapshot应该包含如下信息:

                         a.递归函数调用过程变化的参数,当该参数为引用的形式,不需要包含在Snapshot结构体中。如下面的函数:void SomeFunc(int n, int &retVal);

                          参数n须要包括在里面,参数retVal不须要保存。

                          b.过程保存变量"Stage",通常是一个int型变量来标志当前的阶段。具体看【规则六】

                          c.调用递归函数返回的局部变量(在二分递归和嵌套递归中会出现)。

  

//规则一的例子:递归函数
int SomeFunc(int n, int &retIdx)
{
   ...
   if(n>0)
   {
      int test = SomeFunc(n-1, retIdx);
      test--;
      ...
      return test;
   }
   ...
   return 0;
} 
// 转换成迭代形式
int SomeFuncLoop(int n, int &retIdx)
{
     // (规则一)
    struct SnapShotStruct {
       int n;        // - 输入参数
       int test;     // - 用来保存递归函数返回值的局部变量
                     //     
                     // - retIdx 参数是引用,这里忽略
       int stage;    // - 递归函数调用后,需要到哪个阶段(规则六
// }} 



 

规则二:1.在迭代函数的顶部定义一个局部变量,用来保存递归函数的返回值。

                         a.在迭代函数中,该变量是用来保存递归函数中每一次递归调用的返回值

                         b.如果该递归函数返回值类型为Void, 则可以不定义该局部变量。

                         c.如果有默认的返回值,则用默认的返回值对该局部变量进行初始化。

// 规则二的例子:
int SomeFunc(int n, int &retIdx)
{
   ...
   if(n>0)
   {
      int test = SomeFunc(n-1, retIdx);
      test--;
      ...
      return test;
   }
   ...
   return 0;
}



// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };

    // (Second rule)
    int retVal = 0;  // initialize with default returning value

    ...
    // (Second rule)
    return retVal;
} 

 

规则三:创建一个包含Snapshot结构的栈容器。

// Recursive Function "Third rule" example

// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };

    // (Second rule)
    int retVal = 0;  // initialize with default returning value

    // (Third rule)
    stack<SnapShotStruct> snapshotStack;
    ...
    // (Second rule)
    return retVal;
}  


规则四:1.创建一个Snapshot实例,并对里面的参数进行赋初值,然后把它加入到栈容器中。

// Recursive Function "Fourth rule" example

// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };

    // (Second rule)
    int retVal = 0;  // initialize with default returning value

    // (Third rule)
    stack<SnapShotStruct> snapshotStack;

    // (Fourth rule)
    SnapShotStruct currentSnapshot;
    currentSnapshot.n= n;          // set the value as parameter value
    currentSnapshot.test=0;        // set the value as default value
    currentSnapshot.stage=0;       // set the value as initial stage

    snapshotStack.push(currentSnapshot);

    ...
    // (Second rule)
    return retVal;
}  


 

 规则五:在函数里面建立一个while循环,当栈容器不为空的时候循环,在循环里面弹出一个Snapshot


// Recursive Function "Fifth rule" example

// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };
    // (Second rule)
    int retVal = 0;  // initialize with default returning value
    // (Third rule)
    stack<SnapShotStruct> snapshotStack;
    // (Fourth rule)
    SnapShotStruct currentSnapshot;
    currentSnapshot.n= n;          // set the value as parameter value
    currentSnapshot.test=0;        // set the value as default value
    currentSnapshot.stage=0;       // set the value as initial stage
    snapshotStack.push(currentSnapshot);
    // (Fifth rule)
    while(!snapshotStack.empty())
    {
       currentSnapshot=snapshotStack.top();
       snapshotStack.pop();
       ...
    }
    // (Second rule)
    return retVal;
}  


规则六:     1.当递归函数里面仅有一处自身调用,则将该过程分为两个阶段;第一阶段是在自身调用之前要处理的事情,第二阶段是在自身调用完之后需要处理的事情。

                  2.当递归函数有两处自身调用,则需要将该过程分为三个阶段;Stage 1-->递归调用-->(从第一次递归调用返回)Stage 2(第一阶段递归调用)---》(第二次递归调用返回)Stage 3

                  3.当递归函数有三处自身调用,则需要将该过程分为四个阶段。以此类推。

// Recursive Function "Sixth rule" example
int SomeFunc(int n, int &retIdx)
{
   ...
   if(n>0)
   {
      int test = SomeFunc(n-1, retIdx);
      test--;
      ...
      return test;
   }
   ...
   return 0;
}
/ Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };
    // (Second rule)
    int retVal = 0;  // initialize with default returning value
    // (Third rule)
    stack<SnapShotStruct> snapshotStack;
    // (Fourth rule)
    SnapShotStruct currentSnapshot;
    currentSnapshot.n= n;          // set the value as parameter value
    currentSnapshot.test=0;        // set the value as default value
    currentSnapshot.stage=0;       // set the value as initial stage
    snapshotStack.push(currentSnapshot);
    // (Fifth rule)
    while(!snapshotStack.empty())
    {
       currentSnapshot=snapshotStack.top();
       snapshotStack.pop();
       // (Sixth rule)
       switch( currentSnapshot.stage)
       {
       case 0:
          ...      // before ( SomeFunc(n-1, retIdx); )
          break; 
       case 1: 
          ...      // after ( SomeFunc(n-1, retIdx); )
          break;
       }
    }
    // (Second rule)
    return retVal;
} 

 

 规则七:根据Snapshot结构体stage的值来分别处理各个过程。

// Recursive Function "Seventh rule" example
int SomeFunc(int n, int &retIdx)
{
   ...
   if(n>0)
   {
      int test = SomeFunc(n-1, retIdx);
      test--;
      ...
      return test;
   }
   ...
   return 0;
}


 

// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };

    // (Second rule)
    int retVal = 0;  // initialize with default returning value

    // (Third rule)
    stack<SnapShotStruct> snapshotStack;

    // (Fourth rule)
    SnapShotStruct currentSnapshot;
    currentSnapshot.n= n;          // set the value as parameter value
    currentSnapshot.test=0;        // set the value as default value
    currentSnapshot.stage=0;       // set the value as initial stage

    snapshotStack.push(currentSnapshot);

    // (Fifth rule)
    while(!snapshotStack.empty())
    {
       currentSnapshot=snapshotStack.top();
       snapshotStack.pop();

       // (Sixth rule)
       switch( currentSnapshot.stage)
       {
       case 0:
          // (Seventh rule)
          if( currentSnapshot.n>0 )
          {
             ...
          }
          ...
          break; 
       case 1: 
          // (Seventh rule)
          currentSnapshot.test = retVal;
          currentSnapshot.test--;
          ...
          break;
       }
    }
    // (Second rule)
    return retVal;
} 


 

规则八:1.如果递归函数中有返回值,则在迭代函数中要用一个局部变量来保存循环迭代的结果。如retVal变量            

               2.当循环退出时,该局部变量的值就是递归函数最后的结果

// Recursive Function "Eighth rule" example
int SomeFunc(int n, int &retIdx)
{
   ...
   if(n>0)
   {
      int test = SomeFunc(n-1, retIdx);
      test--;
      ...
      return test;
   }
   ...
   return 0;
}


// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };
    // (Second rule)
    int retVal = 0;  // initialize with default returning value
    // (Third rule)
    stack<SnapShotStruct> snapshotStack;
    // (Fourth rule)
    SnapShotStruct currentSnapshot;
    currentSnapshot.n= n;          // set the value as parameter value
    currentSnapshot.test=0;        // set the value as default value
    currentSnapshot.stage=0;       // set the value as initial stage
    snapshotStack.push(currentSnapshot);
    // (Fifth rule)
    while(!snapshotStack.empty())
    {
       currentSnapshot=snapshotStack.top();
       snapshotStack.pop();
       // (Sixth rule)
       switch( currentSnapshot.stage)
       {
       case 0:
          // (Seventh rule)
          if( currentSnapshot.n>0 )
          {
             ...
          }
          ...
          // (Eighth rule)
          retVal = 0 ;
          ...
          break; 
       case 1: 
          // (Seventh rule)
          currentSnapshot.test = retVal;
          currentSnapshot.test--;
          ...
          // (Eighth rule)
          retVal = test;
          ...
          break;
       }
    }
    // (Second rule)
    return retVal;
} 


规则九:1.在递归函数中,如果有return关键字,在循环中要把它变成continue关键字。                             

             a.如果在递归函数中返回一个值,则用一个局部变量保存该值(如果规则八的retVal),然后再Continue。                  

            b.规则九一般是可选的,主要是为了避免逻辑错误。 

 

// Recursive Function "Ninth rule" example
int SomeFunc(int n, int &retIdx)
{
   ...
   if(n>0)
   {
      int test = SomeFunc(n-1, retIdx);
      test--;
      ...
      return test;
   }
   ...
   return 0;
}

 

// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };
    // (Second rule)
    int retVal = 0;  // initialize with default returning value
    // (Third rule)
    stack<SnapShotStruct> snapshotStack;
    // (Fourth rule)
    SnapShotStruct currentSnapshot;
    currentSnapshot.n= n;          // set the value as parameter value
    currentSnapshot.test=0;        // set the value as default value
    currentSnapshot.stage=0;       // set the value as initial stage
    snapshotStack.push(currentSnapshot);
    // (Fifth rule)
    while(!snapshotStack.empty())
    {
       currentSnapshot=snapshotStack.top();
       snapshotStack.pop();
       // (Sixth rule)
       switch( currentSnapshot.stage)
       {
       case 0:
          // (Seventh rule)
          if( currentSnapshot.n>0 )
          {
             ...
          }
          ...
          // (Eighth rule)
          retVal = 0 ;
          
          // (Ninth rule)
          continue;
          break; 
       case 1: 
          // (Seventh rule)
          currentSnapshot.test = retVal;
          currentSnapshot.test--;
          ...
          // (Eighth rule)
          retVal = test;

          // (Ninth rule)
          continue;
          break;
       }
    }
    // (Second rule)
    return retVal;
} 


 

规则十:为了变换递归函数中的递归调用,在迭代函数中新建一个"Snapshot" 对象,并根据递归调用时候的参数来初始 化"Snapshot" 对象的参数。然后加入到容器栈中,加上 Continue. 如果在递归调用之后还有处理语句,更改当

前"Snapshot" 对象的    stage变量的值到相关阶段,在加入新"Snapshot" 对象到容器栈之前,先把当前更新的"Snapshot"对象压入容器栈。

// Recursive Function "Tenth rule" example
int SomeFunc(int n, int &retIdx)
{
   ...
   if(n>0)
   {
      int test = SomeFunc(n-1, retIdx);
      test--;
      ...
      return test;
   }
   ...
   return 0;
}


 

// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
     // (First rule)
    struct SnapShotStruct {
       int n;        // - parameter input
       int test;     // - local variable that will be used 
                     //     after returning from the function call
                     // - retIdx can be ignored since it is a reference.
       int stage;    // - Since there is process needed to be done 
                     //     after recursive call. (Sixth rule)
    };
    // (Second rule)
    int retVal = 0;  // initialize with default returning value
    // (Third rule)
    stack<SnapShotStruct> snapshotStack;
    // (Fourth rule)
    SnapShotStruct currentSnapshot;
    currentSnapshot.n= n;          // set the value as parameter value
    currentSnapshot.test=0;        // set the value as default value
    currentSnapshot.stage=0;       // set the value as initial stage
    snapshotStack.push(currentSnapshot);
    // (Fifth rule)
    while(!snapshotStack.empty())
    {
       currentSnapshot=snapshotStack.top();
       snapshotStack.pop();
       // (Sixth rule)
       switch( currentSnapshot.stage)
       {
       case 0:
          // (Seventh rule)
          if( currentSnapshot.n>0 )
          {
             // (Tenth rule)
             currentSnapshot.stage = 1;            // - current snapshot need to process after
                                                   //     returning from the recursive call
             snapshotStack.push(currentSnapshot);  // - this MUST pushed into stack before 
                                                   //     new snapshot!
             // Create a new snapshot for calling itself
             SnapShotStruct newSnapshot;
             newSnapshot.n= currentSnapshot.n-1;   // - give parameter as parameter given
                                                   //     when calling itself
                                                   //     ( SomeFunc(n-1, retIdx) )
             newSnapshot.test=0;                   // - set the value as initial value
             newSnapshot.stage=0;                  // - since it will start from the 
                                                   //     beginning of the function, 
                                                   //     give the initial stage
             snapshotStack.push(newSnapshot);
             continue;
          }
          ...
          // (Eighth rule)
          retVal = 0 ;
          
          // (Ninth rule)
          continue;
          break; 
       case 1: 
          // (Seventh rule)
          currentSnapshot.test = retVal;
          currentSnapshot.test--;
          ...
          // (Eighth rule)
          retVal = test;
          // (Ninth rule)
          continue;
          break;
       }
    }
    // (Second rule)
    return retVal;
} 


 


一个详细的例子: 


 

int Fact(long n)
{
	if(0>n)
		return -1;
	if(0 == n)
		return 1;
	else
	{
		return ( n* Fact(n-1));
	}
} 

int FactLoop(long n)
{
	// (First rule)
	struct SnapShotStruct // this can be declared as local structure 
					      //   since it will be only used within this function.
	{
		long inputN;      // parameter that changes
		                  // no local variable
		int stage;        // the stage variable to track where the snapshot has taken
	} ;

	// (Second rule)
	int returnVal;        // the return value at the point  

	// (Third rule)
	stack<SnapShotStruct> snapshotStack;

	// (Fourth rule)
	SnapShotStruct currentSnapshot;
	currentSnapshot.inputN=n;
	currentSnapshot.stage=0; // as initial stage

	snapshotStack.push(currentSnapshot);  

	// (Fifth rule)
	while(!snapshotStack.empty())  
	{     
		currentSnapshot=snapshotStack.top();         
		snapshotStack.pop();       

		// (Sixth rule)
		switch(currentSnapshot.stage)
		{
			// (Seventh rule)
		case 0:
			if(0>currentSnapshot.inputN)
			{
				// (Eighth rule && Ninth rule)
				returnVal = -1;
				continue;
			}
			if(0 == currentSnapshot.inputN)
			{
				// (Eighth rule && Ninth rule)
				returnVal = 1;     
				continue;
			}
			else
			{
				// (Tenth rule)

				// return ( n* Fact(n-1)); this is actually two steps 
				//  (first calling itself, and second with the value returns multiply with current n value.)
				//  this is where we need make a snapshot.
				currentSnapshot.stage=1; // current snapshot is done processing and 
				                          //   only waiting for result of calling itself,
				                          //   so becomes stage "1"
				snapshotStack.push(currentSnapshot);

				// Create a new snapshot for calling itself
				SnapShotStruct newSnapshot;
				newSnapshot.inputN= currentSnapshot.inputN -1 ; // give parameter as parameter given 
				                                                 //   when calling itself.
				newSnapshot.stage = 0 ;                          // since it will start from the begining of 
				                                                 //   the function, give the initial stage
				snapshotStack.push(newSnapshot);
				continue;

			}
			break;
			// (Seventh rule)
		case 1:

			// (Eighth rule)

			returnVal = currentSnapshot.inputN * returnVal;

			// (Ninth rule)
			continue;
			break;
		}
	}
	
	// (Second rule)
	return returnVal;
}   


 

算法08-递归调用转为循环的通用方法 递归转循环的核心是使用栈模拟递归调用栈。通过显式地管理状态,可以避免递归的深度限制。这种方法适用于大多数回溯问题,如组合、排列、子集等。通过这种方法,你可以将任何递归算法转换为循环实现,同时保持逻辑清晰和易于理解。 阅读详情

相关推荐

告别Keil?在Mac上配置STM32CubeIDE + CMSIS-DAP调试器全攻略(含常见报错解决)

本文详细介绍了在Mac平台上配置STM32CubeIDE与CMSIS-DAP调试器的全流程,包括硬件准备、软件安装、工程创建及调试优化。通过实战指南,帮助开发者高效完成STM32开发,解决常见报错问题,提升开发效率。

weixin_30485379的博客 431

递归转循环的通用方法

1.递归 定义:程序调用自身的编程技巧称为递归。 栈与递归的关系:递归是借助于系统栈来实现的。每次递归调用,系统都要为该次调用分配一系列的栈空间用于存放此次调用的相关信息:返回地址,局部变量等。当调用完成时,就从栈空间内释放这些单元,在该函数没有完成前,分配的这些单元将一直保存着不被释放。 2.递归转化为循环 记得有人说过“所有递归都能转化为循环”,某晚睡不着思考了一下这个问题

To be what you what to be! 2万+

VS Code + Codex 在 WSL 中使用的正确姿势

Codex 登录只能在本地完成。文件仍可通过 UNC 路径访问 WSL → 本地 Codex 就能照常工作。避免在 WSL 内重复安装/登录 Codex 扩展。

yangguangwuyue的博客 9822

如何将递归转换为循环

动机 递归效率没有循环高,有额外的方法调用开销 堆栈溢出(stackoverflow) 递归有时挺难理解(不过很多算法用递归最容易实现) 直接法 首先找到递归的结束条件,并且每次递归调用肯定是逼近结束条件(Base Case) 实现一个相同结束条件的循环,每次循环逼近结束条件 public class CountDown { public void countDown(int n) { if(n == 0) return; System.out.println(n + "...");

bill的博客 2840

AVM环视:系统搭建整体流程

文章目录前言一、畸变矫正鱼眼相机二、透视变换三、图像拼接四、图像融合总结 前言 由于正在做AVM环视,所以记录一下整个过程,归纳为一个系列文章,并对期间遇到的错误进行归纳整理。本文主要概括了AVM环视的大致流程和逻辑,不涉及代码部分,仅供思路参考,其中涉及的具体技术会在后期整理为小章节进行分析。 一、畸变矫正 鱼眼相机 做环视基本上使用到的是鱼眼照片,因为鱼眼相机的视角范围可以达到220°到230°,所以一个相机就可以采集到一个面的全部信息,例如汽车具有四个面,那么在汽车的前后左右分别安装一个鱼眼相机.

qq_34468890的博客 6535

ECN实战指南:如何用SAP系统搞定工程变更(附库存处理避坑技巧)

本文详细解析了如何在SAP系统中高效执行工程变更通知(ECN),特别聚焦PP模块的操作流程与库存处理技巧。通过实战案例和系统操作指南,帮助制造业企业避免库存混乱和生产中断,实现从创建到生效的全流程管理。

m5n6o7的博客 1079

算法 递归和循环的转换

【直接转化 】 消除尾递归和单向递归 1. 尾递归 指在递归算法中递归调用语句只有一个 且处于算法的最后private static int factorialByRecurision(int num) { if (num == 1) { return 1; } return num * factorialByRecur

Heqianqian的博客 2906

eCognition易康面向对象分类批量选择样本,批量导出shp

可以的,使用这个工具条最右边那个三角尺manual editing toolbar,这是用来直接指定类别的,咱们可以拿它选完以后把指定的类别转成训练样本。另一个好处是,这个选出来的样本可以直接导出成shp,但select sample是不可以的,只能导出TTAMask也就是栅格掩膜。如果要导出shp,要在转之前导出。中间那条有点点的红线就是我的鼠标轨迹,只要碰到的对象就会全部选中,然后一点3的那个按钮就直接全部划分为林地了,十分丝滑。在弹出来的工作条里,首先选择你的类别,比如这里选一个forest。

qq_61845364的博客 4068

快速排序(递归法与迭代法)

用递归法:代码简洁,但运行速度很慢; 用迭代法:代码略多,但运行速度很快。 本文快速排序方法: 用两个指针i和j,分别指向传进来的低位地址和高位地址。去中间的数为基准值。i从左向右移动,碰到比基准值小的数就继续+1,直至i所指向的数为不小于基准值为止。j从右向左移动,碰到比基准值大的数就继续-1,直至j所指向的数为不大于基准值为止。此时如果满足i小于等于j,就交换i和j所指向数的值,然后i+

lingfeng2019的博客 7789

OpenClaw零基础教程:30分钟搭建你的第一个AI自动化助手

别再看那些满是代码、专业术语的教程了,那些都是给程序员看的。这篇教程,我把所有步骤拆到了极致,你跟着点鼠标就行,点错了都没关系,大不了重装一遍,5分钟的事。

2601_94871597的博客 96

WPF中使用TreeView封装组合控件TreeView+DataGrid

wpf的功能非常强大,很多控件都是原生的,但是要使用TreeView+DataGrid的组合,就需要我们自己去封装实现。功能如上图所示, 目前基本上把常用的样式都实现了,购买源码后,可以自行修改样式。本文源码效果如下,(搞了好几天,的确有难度,所以源码也收费,便宜,赚点辛苦费)第一种:技术的选择是TreeView(也就是本文的演示)。这2个图都是第三方控件自带的,并且都是收费使用。首先说明一下,实现上面的效果,有3种方法。本文演示的是使用TreeView的实现。第二种:技术的选择是DataGrid。

故里2130 1650

C语言实现求解斐波那契数列的四种方法及优化处理(递归,迭代,特殊性质公式,矩阵快速幂)

C语言实现求解斐波那契数列的四种方法及优化处理(递归,迭代,特殊性质公式,矩阵快速幂)

Ty_Man的博客 1万+

帆软报表导出各种格式之后台导出

我们前面介绍了帆软报表在界面上的导出是通过类似的URL:http://localhost:8075/webroot/decision/view/report?op=export&sessionID=10653244-3e46-408c-bc54-f89a214a9bc7&format=image&extype=PNG 来完成的,就是带OP=export以及format参数来完成的。如果不从界面传参数,比如我们自己实现了一个HTTP接口,也可以通过传参数format来完成各种格式的导

帆软爱好者的专栏 4270

【经典算法实现 43】理解FFT快速傅里叶变换 及 IFFT快速傅里叶逆变换(迭代法 和 递归法)

【经典算法实现 43】理解FFT快速傅里叶变换一、FFT公式推导二、图示求解过程(分治法)2.1 第一次奇偶分组 z = 22.2 第二次奇偶分组 z = 12.3 第三次奇偶分组 z = 0三、图示求解过程(递归法)3.1 第一次递归 z = 33.2 第二次递归 z = 23.3 第三次递归 z = 13.4 第四次递归 z = 0四、代码实现(递归法)五、代码实现(分治法) 一、FFT公式推导 一维傅里叶变换: F(u)=∑M=0M−1f(x)e−jux2πM,u=0,1,2,⋯ ,M−1F(u)

|~~~热爱生活、努力学习的小伙汁~~~| 4197

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

C语言 - 快速幂 - 迭代法+递归法 - 详细讲解

快速幂的作用: 解决 求 a ^ n 的问题 (n可以大于1e18), 如果用for循环的话,毫无疑问直接炸掉 …… 所以也就用了算法复杂度在 o(log n)的快速幂算法来解决此类问题。 快速幂递归法(基于二分思想): 那么既然要用到二分法那么怎么二分? 既然要递归那么如何递归? 第一个问题如何二分 ? 就以2 ^ 10 为例 , 我们可以以指数入手进行二分 , 10 是一个偶数 ,那么 二分一下就是 2^5 * 2^5 ,之后 2^5 中 5为奇数 那么就让 2^5 = 2 * 2^4 ,那么就有了2^

SOAR 2356

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

分治法 —— 快速排序(递归,迭代,非递归)

快速排序 快速排序三种方法,你值得参考!!!快速排序1,快速排序之递归Code 递归2,快速排序之迭代Code 迭代3,快速排序之非递归Code 非递归4,结语 快速排序在所有排序中基本上速度是最快的啦 (前提是基准元素要选的好,没选好基准元素很可能变为冒泡排序) 快速排序算法思想是分治策略,但可以有多种手段来实现 1,快速排序之递归 其实快速排序之递归是传统的快速排序。为什么说是传统的呢? 大部分的快速排序无论是在教材上还是在一些博客上基本采用递归分治来实现。因为此方法比较好懂 递归快速排序一般都是两个游

重燃2020!!! 3339

【经典算法实现 44】理解二维FFT快速傅里叶变换 及 IFFT快速傅里叶逆变换(迭代法 和 递归法)

【经典算法实现 44】理解二维FFT快速傅里叶变换 及 IFFT快速傅里叶逆变换(迭代法 和 递归法)一、二维FFTFFTFFT快速傅里叶变换 公式推导二、二维FFTFFTFFT 及 IFFTIFFTIFFT代码实现(迭代法) 前面我们实现了一维快速傅里叶变换《【经典算法实现 43】理解FFT快速傅里叶变换 及 IFFT快速傅里叶逆变换(迭代法 和 递归法)》 本文开始二维傅里叶变换的公式推导及代码实现 一、二维FFTFFTFFT快速傅里叶变换 公式推导 二维傅里叶变换: F(u,v)=∑Mx=0Mx

|~~~热爱生活、努力学习的小伙汁~~~| 1万+

用C++语言编写将递归函数转为循环遍历的示例

摘要:本文展示了将递归程序转换为迭代程序的两种方法。首先用递归实现阶乘计算(factorial_recursive),然后通过栈数据结构模拟递归调用过程(factorial_stack),实现了相同的功能。后者将递归调用转化为显式的栈操作,通过循环和条件判断完成计算。代码示例演示了计算5的阶乘,两种方法结果一致(120)。这种转换技术提供了一种通用的递归改循环方案,适用于需要消除递归或优化性能的场景。

yth796的专栏 255

【算法笔记】快速幂的两种写法(递归法+迭代法)

快速幂的递归法 // 求a^b%m ll binaryPow(ll a, ll b, ll m) { if (b == 0) return 1; if (b %2 == 1) { return a * binaryPow(a, b-1, m) % m; } else { ll tmp = binaryPow(a, b/2, m); return tmp * tmp % m...

Y_CanFly的小小博客 1345

c语言:递归与迭代

它却没有得出结果,这是为什么呢,因为,函数在内部多次调用了自己,产生了大量的重复计算,导致计算量巨大,代码执行效率非常低,让计算机也无法快速得出结果,这个例子告诉我们,递归是有使用条件的 ,如果要设计一个需要重复计算的程序,不能无脑使用递归,而是首先要思考递归能不能用,是否能让代码简洁的同时,更加高效,那么此类例子我们如何解决呢?可以看到,很快就得到了结果,但是答案是错误的,因为要求的数太大,一个字节无法表示,但是我们可以很直观的看见两者的差别,在这这样一个例子中,使用迭代会优于使用递归。

qq_58761784的博客 1432

【二叉搜索树最近公共祖先】迭代法VS递归法解决

通过本文的讲解,我们深入理解了 BST 中 LCA 问题的递归法和迭代法实现。递归法简洁直观,适合教学和小规模数据;迭代法高效稳定,适合大规模数据或对性能敏感的场景。在实际应用中,可以根据具体需求选择合适的方法,并进一步优化以适应更复杂的场景。

2501_90701388的博客 2105

快速排序实现(递归与非递归)

快速排序热乎着,不来看看么

weixin_57663528的博客 2671

从快速排序来看迭代和递归的区别

<br />#include<iostream> using namespace std; void QuickSort(int [],const int,const int); int Partition(int [],const int,const int); int main() { int arr[10] = {12,14,8,4,9,15,3,11,25,99}; for(int i = 0;i <

lyt578639125的专栏 881

快速排序的递归实现和非递归实现

找比基准值小的值,找到后停在此位置,然后指向首位置的left开始向右走,找到比基准值大的值,找到后停在此位置,然后将此时left和right分别指向的值进行交换,再继续刚才的找法。进入循环,然后判断cur位置的值是否小于基准值,若小于,再判断prev+1后的位置是否与此时cur不在同一位置,若是,则交换此时prev和cur位置的值。首先定义变量prev,并用其保存left的值,再定义变量cur,cur保存left+1的值,并定义基准值的位置key是left的位置。因此使用非递归形式进行排序是必要的。

2301_80667185的博客 1968
上一篇: 如何减少C++程序的重复编译?
下一篇: [SQL Server]如何快速查找使用了某个字段的所有存储过程?
xiaoding133
博客等级 码龄19年 415粉丝 159原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值