Recursão e divisão e conquista [estrutura de dados e algoritmo]

Artigos anteriores
1 Introdução - Conceitos básicos da estrutura de dados
2 Introdução - Algoritmo
3 Lista de sequência linear linear e conceitos de lista vinculada e sua implementação de código
4 Ordem de pesquisa + Metade + Índice + Hash
5 Inserção Sort-Hill Sort-Selection Sort-Bubble Sort -Quick Sort-Cardinal Sort-External Sort-Merge Sort

1 Definição de recursão

  • Uma sub-rotina (ou função) chama a si mesma direta ou indiretamente por meio de uma série de instruções de chamada, que é chamada de recursão.
  • A recursão é um método básico de descrição e solução de problemas.

Chamada recursiva direta

void A()
{
    
    
 ...
	A();
 ...
}

Recursão de chamada indireta

void B()
{
    
    
...
C();
...
}

void C()
{
    
    
 ...
	B();
 ...
}

2 Solução recursiva e não recursiva da sequência de Fibonacci

A recursão de cauda pode ser convertida em escrita não recursiva
A recursão da cauda significa que a recursão só ocorre quando o retorno

Insira a descrição da imagem aqui
Solução recursiva

int f(int n)
{
    
    
	if(n<=1)
		return n;//结束条件
	else
		return(f(n-1)+f(n-2));//递归方程
} 

Solução não recursiva

int f(int n)
{
    
    
	int pre,now,next,j;
	if(n<=1)return(n);
	else
	{
    
    
		pre=0;now=1;
		for(j=2;j<=n;j++)
		{
    
    
			next=pre+now;
			pre=now;
			now=next
		}
		return(next);
  	}

}

3 Soluções recursivas e não recursivas para detecção de string de palíndromo

    Se uma string é lida da esquerda para a direita e lida da direita para a esquerda é exatamente a mesma (não diferencia maiúsculas de minúsculas), então esta string é chamada de palíndromo. Por exemplo, "meio-dia", "madame", etc. são todas strings de palíndromo .

Solução recursiva

bool palindrome(string &s,unsigned h,unsigned t)
{
    
    
	if (h>=t) return 1;
	if(tolower(s[h])==tolower(s[t]))
		return palindrome(s,h+1,t-1);
	else
		return 0;
}

Solução não recursiva

bool palindrome(string &s)
{
    
    
	int h=0,t=strlen(s)-1;
	while(h<=t)
	{
    
    
		if(s[h]!=s[t])return 0;
		h++;t--;
	}
	return 1;
}

4 Divida e conquiste a recursão

4.1 Divida e conquiste o pensamento recursivo

  • Resolva esses k subproblemas separadamente. Se o tamanho do subproblema ainda não for pequeno o suficiente, divida-o em k subproblemas e proceda recursivamente até que o problema seja pequeno o suficiente para encontrar sua solução facilmente.
  • Combine a solução do problema de pequena escala encontrada na solução de um problema de grande escala e, gradualmente, encontre a solução do problema original de baixo para cima.

4.2 Condições aplicáveis ​​da lei dividir para conquistar

  • O tamanho do problema pode ser facilmente resolvido reduzindo-o até certo ponto;
  • O problema pode ser decomposto em vários problemas idênticos de menor escala, ou seja, o problema tem a propriedade de subestrutura ótima ( premissa )
  • As soluções dos subproblemas decompostos pelo problema podem ser combinadas na solução do problema; ( se você tiver os dois primeiros, mas não o terceiro, você pode considerar o uso de algoritmo guloso e programação dinâmica )
  • Os subproblemas decompostos pelo problema são independentes uns dos outros, ou seja, os subproblemas não contêm subproblemas comuns. ( Este recurso projeta a eficiência do método de dividir e conquistar )

4.3 As etapas básicas de dividir e conquistar

Preste atenção às notas

{
    
    
	if ( | P | <= n0) adhoc(P); //解决小规模的问题
	divide P into smaller subinstances P1,P2,...,Pk;//分解问题
		for (i=1,i<=k,i++)
			yi=divide-and-conquer(Pi); //递归的解各子问题
		return merge(y1,...,yk); //将各子问题的解合并为原问题的解
}

4.4 Três maneiras de resolver o cálculo da complexidade recursiva

4.4.1 Método de substituição

Pré-requisito (ignorar os detalhes e adicioná-los se forem considerados importantes posteriormente)
T (n) consiste em duas partes, uma éSoma do tempo de cálculo para cada pequena parte + Tempo de decomposição e tempo de reconciliação f (n)

Insira a descrição da imagem aqui
A ideia principal

  1. Adivinhe a forma da solução.
  2. Use a indução matemática para encontrar a constante que torna a solução realmente eficaz

Insira a descrição da imagem aqui

Insira a descrição da imagem aqui

4.4.2 Expansão direta de método iterativo

Insira a descrição da imagem aqui

4.4.3 Método principal

Insira a descrição da imagem aqui

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

5 Exemplo de aplicação

    Supondo que haja n dados a [n], para imprimir todas as permutações desses n dados, considere o método recursivo PrintPermutation.

  1. O elemento na primeira posição pode ser qualquer um desses n elementos. Você pode usar swap para trocar a primeira posição por outras posições para obter a diferença no primeiro elemento de posição, e o resto da chamada recursiva imprime todos. A função de organização PrintPermutation é concluído. No entanto, deve-se notar que eles devem ser trocados de volta para facilitar o manuseio correto posteriormente.

  2. Dentro da função recursiva, o elemento na primeira posição atual (a segunda posição) será trocado com os elementos de posição n-2 restantes; o elemento na primeira posição atual (a terceira posição) será trocado com o n-Exchange restante de 3 elementos de posição; ...; O elemento na última enésima posição significa que as n-1 posições anteriores foram processadas e podem ser impressas. Portanto, a condição de impressão recursiva é a posição k = n, esta também é uma saída recursiva

a [] armazena os dados k representa a primeira posição de troca, geralmente 1, n é o número de dados.

void PrintPermutation(int a[], int k, int n){
    
    
	if (k == n){
    
    
		for (int i = 1; i < n + 1; ++i){
    
    
			cout << a[i] << " ";
		}
		cout << endl;
		return;
	}
	else{
    
    
		for (int i = k; i < n+1; ++i){
    
    
			Swap(a[k], a[i]);
			PrintPermutation(a, k + 1, n);
			Swap(a[k], a[i]);
		}
	}
}


int main()
{
    
    
	int *a, len;
	cout << "len:" << endl;
	cin >> len;
	a = new int[len+1];
	if (!a)return -1;
	for (int i = 1; i < len + 1; ++i)
		a[i] = i;
	PrintPermutation(a, 1, len);
}

Se houver omissões e erros, indique-os.

Acho que você gosta

Origin blog.csdn.net/weixin_44972997/article/details/114443152
Recomendado
Clasificación