数据结构 笔记:递归的思想与应用

递归是一种数学上分而自治的思想

-将原问题分解为规模较小的问题进行处理

·分解后的问题与原问题的类型完全相同,单规模较小

·通过小规模问题的解,能够轻易求得原问题的解

-问题的分解是有限的(递归不能无限进行)

·当边界条件不满足时,分解问题(递归继续进行)

·当边界条件不满足时,直接求解(递归结束)

递归在程序设计中的应用

-递归函数

·函数体中存在自我调用的函数

·递归函数必须有递归出口(边界条件)

·函数的无限递归将导致程序崩溃

递归思想的应用

-求解:Sum(n) = 1 + 2 + 3 + ... + n

unsigned int sum(unsigned int n)
{
    if( n > 1 )
    {
        return n + sum(n - 1);
    }
    else
    {
        return 1;
    }
}

斐波拉契数列

-数列自身递归定义:1,1,2,3,5,8,13,21,...

unsigned int fac(unsigned int n)
{
    if( n > 2 )
    {
        return fac(n - 1) + fac(n - 2);
    }

    if((n == 2) || (n == 1))
    {
        return 1;
    }

    return 0;
}

用递归的方法编写函数求字符串长度

unsigned int _strlen_(const char* s)
{
    return s ? (*s ? (1 + _strlen_(s + 1)) : 0) : 0;
}

单项链表的转置

struct Node
{
    int value;
    Node* next;
};

Node* create_list(int v,int len)
{
    Node* ret = NULL;
    Node* slider = NULL;

    for(int i = 0;i < len ; i++)
    {
        Node* n = new Node();

        n->value = v++;
        n->next = NULL;

        if(slider == NULL)
        {
            slider = n;
            ret = n;
        }
        else
        {
            slider->next = n;
            slider = n;
        }
    }
    return ret;
}

void destroy_list(Node* list)
{
    while(list)
    {
        Node* del = list;

        list = list->next;
        delete del;
    }
}

void print_list(Node* list)
{
    while(list)
    {
        cout << list->value << "->";

        list = list->next;
    }
    cout << "NULL" << endl;
}

Node* reverse(Node* list)
{
    if( (list == NULL) || (list->next == NULL))
    {
        return list;
    }
    else
    {
        Node* guard = list->next;
        Node* ret = reverse(list->next);

        guard->next = list;

        list->next = NULL;

        return ret;
    }
}

单向排序链表的合并

Node* merge(Node* list1,Node* list2)
{
    if(list1 == NULL)
    {
        return list2;
    }
    else if(list2 == NULL)
    {
        return list1;
    }
    else if(list1->value < list2->value)
    {
        return (list1->next = merge(list1->next,list2),list1);
    }
    else
    {
        return (list2->next = merge(list1,list2->next),list2);
    }
}

汉诺塔问题

-将木块借助B柱由A柱移动到C柱

-每次只能移动一个木块

-只能出现小木块在大木块之上

void HanoiTower(int n,char a,char b,char c)
{
    if(n == 1)
    {
        cout << a << "-->" << c << endl;
    }
    else
    {
        HanoiTower(n - 1,a,c,b);
        HanoiTower(1,a,b,c);
        HanoiTower(n-1,b,a,c);
    }
}

全排列问题

void permutation(char* s,char* e)
{
    if(*s == '\0')
    {
        cout << e << endl;
    }
    else
    {
        int len = strlen(s);

        for(int i = 0;i < len;i++)
        {
            if( ( i == 0) || (s[0] != s[i]))
            {
                swap(s[0],s[i]);
                permutation(s+1,e);
                swap(s[0],s[i]);

            }
        }
    }
}

函数调用过程回顾

-程序运行后有一个特殊的内存区供函数调用

·用于保存函数中的实参,局部变量,临时变量,等

·从开始地址开始往一个方向增长(如:高地址==>底地址)

·有一个专用的“指针”,表示当前已使用内存的“顶部”

void r_print_even(Node* list)
{
    if(list != NULL)
    {
        r_print_even(list->next);

        if((list->value % 2) == 0)
        {
            cout << list->value << endl;
        }
    }
}

八皇后问题

template <int SIZE>
class QueueSolution : public Object
{
protected:
    enum { N = SIZE + 2};

    struct Pos : public Object
    {
        Pos(int px = 0,int py = 0) : x(px),y(py){}
        int x;
        int y;
    };
    int m_chessboard[N][N];

    Pos m_direction[3];
    LinkList<Pos> m_solution;
    int m_count;

    void init()
    {
        m_count = 0;
        for(int i = 0; i<N; i +=(N-1))
        {
            for(int j = 0;j<N;j++)
            {
                m_chessboard[i][j] = 2;
                m_chessboard[j][i] = 2;
            }
        }

        for(int i =1;i<=SIZE;i++)
        {
            for(int j = 1;j<=SIZE;j++)
            {
                m_chessboard[i][j] = 0;
            }
        }

        m_direction[0].x = -1;
        m_direction[0].y = -1;
        m_direction[1].x = 0;
        m_direction[1].y = -1;
        m_direction[2].x = 1;
        m_direction[2].y = -1;
    }

    void print()
    {
        for(m_solution.move(0); !m_solution.end();m_solution.next())
        {
            cout << "(" << m_solution.current().x << ", " << m_solution.current().y<<") ";
        }

        cout << endl;

        for(int i = 0;i<N;i++)
        {
            for(int j = 0;j<N;j++)
            {
                switch(m_chessboard[i][j])
                {
                    case 0:cout << "  " ;break;
                case 1: cout << " #" ;break;
                case 2:cout << " *" ;break;
                }
            }
            cout << endl;
        }
        cout << endl;
    }

    bool check(int x,int y,int d)
    {
        bool flag = true;

        do
        {
            x += m_direction[d].x;
            y += m_direction[d].y;
            flag = flag && (m_chessboard[x][y] == 0);
            //cout << flag;
        }
        while(flag);

        return (m_chessboard[x][y] == 2);
    }

    void run(int j)
    {
        if(j <= SIZE)
        {
            for(int i = 1;i<=SIZE;i++)
            {

                if(check(i,j,0) && check(i,j,1) && check(i,j,2))
                {
                    m_chessboard[i][j] = 1;

                    m_solution.insert(Pos(i,j));

                    run(j + 1);


                    m_chessboard[i][j] = 0;

                    m_solution.remove(m_solution.length() - 1);
                }
            }
        }
        else
        {
            m_count++;

            print();
        }
    }
public:
    QueueSolution()
    {
        init();
    }

    void run()
    {
        run(1);

        cout << "Total : " << m_count <<endl;
    }
};

总结:

-程序运行后的栈存储区专供函数调用使用

-栈存储区用于保存实参,局部变量,临时变量,等

-利用栈存储区能够方便的实现回溯算法

猜你喜欢

转载自blog.csdn.net/qq_29962483/article/details/83745826
今日推荐