【数据结构】单链表的递归算法

设计递归算法的方法

主要是求递归模型,递归模型的求解类似于(其实就是)数学中的归纳法。递归模型中应该包含递归体递归出口两部分。

【数据结构】单链表的递归算法_第1张图片

【数据结构】单链表的递归算法_第2张图片

代码如下:

#include 

#define NUM 8
int A[NUM] = { 102,102,32,44,202,32,61,56 };

int min(int a,int b)
{
    if (a < b)return a;
    else return b;
}

int F(int A[], int i)//使用递归求数组A[]中A[0]~A[i]的最小值
{
    if (i == 0)return A[0];
    else
    {
        return min(F(A, i - 1), A[i]);
    }
}

int main()
{
    printf("F: %d\n", F(A, NUM - 1));
    return 0;
}

递归的魅力-不带头结点的单链表的递归算法

#include 
#include 

typedef struct Node {
    int data;
    struct Node* next;
}Node, * LkList;

void CreatLkList(LkList& L, int n);
void Tranvers_Twd(LkList L);//递归正向遍历
void Tranvers_Bk(LkList L);//递归反向遍历
void DestoryList(LkList& L);

int main()
{
    LkList L;
    CreatLkList(L, 5);
    printf("正向遍历:\n");
    Tranvers_Twd(L);
    printf("反向遍历:\n");
    Tranvers_Bk(L);
    printf("销毁链表:\n");
    DestoryList(L);
	return 0;
}


void CreatLkList(LkList& L,int n)//递归创建不带头结点的单链表
{
    if (n == 0)//终止条件
    {
        L = NULL;
    }
    else
    {
        L = (LkList)malloc(sizeof(Node));
        if (!L)exit(0);

        scanf_s("%d",&(L->data));
        CreatLkList(L->next, n - 1);
    }
}

void Tranvers_Twd(LkList L)//递归正向遍历
{
    if (L == NULL)return;
    printf("%d\n",L->data);
    Tranvers_Twd(L->next);
}
void Tranvers_Bk(LkList L)//递归反向遍历
{
    if (L == NULL)return;
    Tranvers_Bk(L->next);
    printf("%d\n", L->data);
}

void DestoryList(LkList& L)
{
    if (L)
    {
        DestoryList(L->next);
        printf("free:%d\n", L->data);//显示释放过程
        free(L);
        L = NULL;
    }
}

递归函数的位置很重要,它决定了该递归从哪里展开,也就会有不同的效果。

void Tranvers_Twd(LkList L)//递归正向遍历
{
    if (L == NULL)return;
    printf("%d\n",L->data);
    Tranvers_Twd(L->next);
}
void Tranvers_Bk(LkList L)//递归反向遍历
{
    if (L == NULL)return;
    Tranvers_Bk(L->next);
    printf("%d\n", L->data);
}

比如上文的链表的正向遍历和反向遍历,他们的差别只是递归函数的位置不同!我们知道代码是从前往后执行的,如果递归函数是在最后调用(尾递归),我们递归展开一次就会是这样:

void Tranvers_Twd(LkList L)//递归正向遍历
{
    if (L == NULL)return;
    printf("%d\n", L->data);
        if (L->next == NULL)return;
        printf("%d\n", L->next->data);
        Tranvers_Twd(L->next->next);
}

再展开一次就是这样:

void Tranvers_Twd(LkList L)//递归正向遍历
{
    if (L == NULL)return;
    printf("%d\n", L->data);
        if (L->next == NULL)return;
        printf("%d\n", L->next->data);
            if (L->next->next == NULL)return;
            printf("%d\n", L->next->next->data);
            Tranvers_Twd(L->next->next->next);
}

 ...展开下去就是从L开始一直打印两边中的节点的数据,直到L->next....->next=NULL就会终止。

同样的道理,我们对反向遍历函数Tranvers_Bk展开两次:

void Tranvers_Bk(LkList L)//递归反向遍历
{
    if (L == NULL)return;
        if (L->next == NULL)return;
            if (L->next->next == NULL)return;
            Tranvers_Bk(L->next->next->next);
            printf("%d\n", L->next->next->data);
        printf("%d\n", L->next->data);
    printf("%d\n", L->data);
}

 可以看到,是从内往外打印的!这就是递归反向遍历链表的道理!

总的来说,递归函数前的是有外入内,递归函数后的是有内出外。

void f()
{
	//由外到内
	f();//递归体
	//由内到外
}

你可能感兴趣的:(数据结构与算法,链表,递归,数据结构,单链表)