Step on the pit when using recursion - be sure to give the end condition

Keywords: data structure

preface

When I first learned programming in freshman year, I had a preliminary contact with the concept of recursion. At that time, I also used it to complete several homework problems such as factoring and fiboracci sequence, but I found that up to now, I have been taking the course of data structure and algorithm, and I still have a vague understanding of recursion, Even many times, the result cannot be output because the end condition is forgotten. Now take out the two typical questions and record them. Urge yourself to write the recursive end condition next time!!!

Topic 1: creation of binary tree and traversal output of front, middle and back order

#include <iostream>
using namespace std;
//If necessary, you can add your own header file
/*-------begin--------*/
#include <stdio.h>  
#include <stdlib.h>  
/*-------end--------*/  
 
typedef char DataType;
 
//Binary tree node definition 
struct node
{
   DataType data; //Store node data 
   struct node *lchild, *rchild ; //Left and right child pointers 
};
typedef struct  node  BiTree;
typedef struct  node  *ptree;

//Function can be used directly. Function: output node data
void print(DataType d)
 {
   cout<<d<<" ";
 }

/*
Function name: createtree
 Function function: to create a binary tree, you are required to enter the pre root sequence of the binary tree (see the description on the left for the specific input method), create the corresponding binary tree, and return the root node pointer of the binary tree 
Parameter: None 
Return value: root node pointer of binary tree 
*/ 
BiTree *createBiTree() {
//Please fill in the code here to complete the function of creating a binary tree and returning the root node pointer of the binary tree    
/*-------begin--------*/
  BiTree *p=NULL;   	
char c;
cin>>c;
if(c!='#'){
p=(ptree)malloc(sizeof(BiTree));
p->data=c;
	p->lchild=createBiTree();
	p->rchild=createBiTree();
}

    return p;
    
/*-------end--------*/    
}

/*
Function name: preOrder
 Function function: first traverse the root binary tree 
Parameter: binary tree root node pointer 
Return value: None 
*/
void preOrder(BiTree *T) 
{
//Please fill in the code here to complete the function of traversing the binary tree first    
/*-------begin--------*/
//Idea: recursion, first access the root node, and then access the left and right nodes respectively    
if(T!=NULL){
print(T->data);
preOrder(T->lchild);
preOrder(T->rchild);	
}

/*-------end--------*/  
}
 
/*
Function name: inOrder
 Function function: middle root traversal binary tree 
Parameter: binary tree root node pointer 
Return value: None 
*/  
void inOrder(BiTree *T) 
{
    //Please fill in the code here to complete the middle root traversal binary tree function    
/*-------begin--------*/
if(T!=NULL){
	inOrder(T->lchild);
print(T->data);
inOrder(T->rchild);  
} 
    
/*-------end--------*/  
}

/*
Function name: postOrder
 Function function: traversing binary tree after root 
Parameter: binary tree root node pointer 
Return value: None 
*/  
 void postOrder(BiTree *T)  
    {  
      //Please fill in the code here and complete the root traversal binary tree function    
/*-------begin--------*/
   if(T!=NULL){
   	postOrder(T->lchild);
postOrder(T->rchild);   
print(T->data);
   }

/*-------end--------*/  
    }  
 
 

The main functions are as follows:

int main(void)  
{  
 BiTree  *T;  
     T =  createBiTree(); //Call the function of creating binary tree to get the root node pointer of binary tree
 
	 
    preOrder(T);//Call the root first traversal binary tree and output the node function of binary tree in the order of root first traversal 
    cout<<endl; //Line feed
	inOrder(T);//Call the middle root to traverse the binary tree, and output the binary tree node function according to the middle root traversal order 
	cout<<endl; 
    postOrder(T);//After the call, the root traverses the binary tree and outputs the node function of the binary tree in the order of the root traversal 
   
   return 0;
}  

Note: the conditions for the end of recursion are: T==NULL;
Note: the code is written in c, but the c + + library is used in the main function of the evaluation platform, but I don't have the permission to modify the main function, so I added a few lines of c + + specification to the code I wrote.

Topic 2: Huffman coding and decoding applications

Test input: 5 2 7 4 5 19

Expected output: (traverse the Huffman tree in medium order and output the Huffman code of the corresponding leaf)

7 00
5 010
2 0110
4 0111
19 1

The code is as follows:

//huffman tree
#include <stdio.h>
#include <stdlib.h>
#define MAXINT 10000

char huffcode[10]={'\0'}; 

//define huffman node 
struct HtNode{
	int ww;
	int parent,llink,rlink;
};

//define huffman tree
struct HtTree{
	struct HtNode *ht;//An array of all nodes
	int m;//m effective nodes, that is, those really used for coding, can be understood as external nodes in the tree structure 
	int root;//Subscript of root node 	 
};

typedef struct HtTree *PHtTree;

//create huffman tree
//Coding using backtracking 
PHtTree huffman(int m,int *w){
	PHtTree pht;
	int i,j,x1,x2,m1,m2;
	//Apply for memory space and check whether each link is allocated successfully
	pht=(PHtTree)malloc(sizeof(struct HtTree));
	if(pht==NULL){
		printf("create tree failed!");
		return NULL;
	}
	pht->ht=(struct HtNode*)malloc(sizeof(struct HtNode)*(2*m-1)); 
	if(pht->ht==NULL){
			printf("create node of tree failed!");
		return NULL;
	}
	//initialize array of ht
	for(i=0;i<2*m-1;i++){
	pht->ht[i].llink=-1;
	pht->ht[i].rlink=-1;	
	pht->ht[i].parent=-1;
	if(i<m){
		pht->ht[i].ww=w[i];
	}
	else pht->ht[i].ww=-1; 
	}
	
	//Each loop constructs an internal node
	for(i=0;i<m-1;i++){
		m1=MAXINT;m2=MAXINT;
		x1=-1;x2=-1;//m1m2 is the weight and x1x2 is the subscript 
		//Find two nodes without parent node with minimum weight
		for(j=0;j<m+i;j++){
			if(pht->ht[j].ww<m1&&pht->ht[j].parent==-1){
				m2=m1;x2=x1;m1=pht->ht[j].ww;x1=j;
			}//Minimum weight 
			else if(pht->ht[j].ww<m2&&pht->ht[j].parent==-1){
				m2=pht->ht[j].ww;
				x2=j;
			}}//Sub minimum weight  
		pht->ht[x1].parent=m+i;
		pht->ht[x2].parent=m+i;	
		pht->ht[m+i].ww=m1+m2;
		pht->ht[m+i].llink=x1;
		pht->ht[m+i].rlink=x2;
		
	} 
	pht->root=2*m-2;
	return pht;	
}

//decoding
//When using recursion, you must pay attention to the end condition of recursion!!! 
void print(PHtTree T,int num,int i){
	if(T->ht[num].llink==-1&&T->ht[num].rlink==-1){
		printf("%d ",T->ht[num].ww);
		int j;
		for(j=0;j<i;j++){
			printf("%c",huffcode[j]);
		}
		printf("\n");
		return ; 
	}
	huffcode[i]='0';
	print(T,T->ht[num].llink,i+1);
	huffcode[i]='1';
	print(T,T->ht[num].rlink,i+1);
} 


int main(){
	int m,i,arr[100];
	scanf("%d",&m);
	for(i=0;i<m;i++){
		scanf("%d",&arr[i]);
	}
	PHtTree T=huffman(m,arr);
	print(T,T->root,0);
	return 0;
} 


Write at the end:
The problem of Huffman coding is not entirely a pot of recursive end conditions. The book has the structure of Huffman tree and coding process (huffman() function), but I didn't understand it at first. I copied it wrong (covering my face), PHT - > HT [X1]. Parent = m + I; pht->ht[x2].parent=m+i; pht->ht[m+i].ww=m1+m2; pht->ht[m+i].llink=x1; pht->ht[m+i].rlink=x2; These steps should be performed after the end of the second layer of recursion and before the end of the first layer of for loop, not in the second layer of for loop, because the second layer of for loop is a process of finding two minimum nodes and jumping out to merge nodes when found.

epilogue

This is my personal study record. It's written casually. If you can brush this article and see it here, thank you sincerely!

Posted by Michdd on Sun, 21 Nov 2021 19:09:36 -0800