二叉树:深度优先遍历

/*

   深度优先搜索的实现:

    关于深度优先遍历,找不到最短路径,暂时未作分析,容后补上,以作记录

    补充如下:举例如迷宫问题,都是遍历,譬如深度优先遍历、广度优先遍历。但深度优先可以最快速度找到出口,而广度优先遍历花的时间则更多;

                      但深度优先遍历,不一定找到最优(最短)路径,而广度优先遍历则一定能找到最短优先路径(加入有的话)。

                      从代码分析理解,深度优先遍历,因为使用了栈的后进先出结构,注定是做一根筋式的查找,不撞南墙不回头。而且,可能会把所有的路径都给走一遍(这是基于遍历的先后方向,如下代码所示)。

                      相反,广度优先遍历,因为使用了队列的先进先出结构,所有有分叉的结点,都遵循天女散花式,齐头并进的遍历。最终,某个方向的遍历,最先找到出口。因为所有分叉都是齐头并进式的遍历,则最先找到出口的,就是最短路径(但,可能不是唯一的最短路径)。

网上另一种标识图块状态的做法没看明白,此处借鉴了 linxu c编成 一站式学习的编码,纯属学习,在此作声明

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct __ElemType
{
    int y;
    int x;
}ElemType;

typedef struct __stackInfo
{
    ElemType *pData;
    unsigned int top;
    unsigned int capacity;
} stackInfo;

/* 初始化 */
int initStack(stackInfo **ppS, unsigned int size)
{
    if (NULL == ppS)
    {
        printf("ppNewStack point address is not exist\n");
        return -1;
    }

    stackInfo *pNewStack = (stackInfo *)malloc(sizeof(stackInfo));
    if (NULL == pNewStack)
    {
        printf("ppNewStack malloc fail\n");
        return -1;
    }

    pNewStack->pData = (ElemType *)malloc(sizeof(ElemType)*size);
    if (NULL == pNewStack->pData)
    {
        printf("ppNewStack databuf malloc fail\n");
        
        /* 前面几篇代码就少了这里,务必要小心,记个坑: 一旦直接推出,则泄漏内存pNewStack */
        free(pNewStack);
        return -1;
    }
    
    pNewStack->capacity = size;
    pNewStack->top = 0;

    *ppS = pNewStack;

    return 0;
}
/* 入栈 */
int pushStack(stackInfo *pS, ElemType *val)
{
    if (NULL == pS)
    {
        printf("pStack point NULL\n");
        return -1;
    }
    
    if (pS->capacity == pS->top)
    {
        printf("pStack full\n");
        return -1;
    }
    
    memcpy(&pS->pData[pS->top], val, sizeof(ElemType));
    pS->top++;
    
    return 0;
}
/* 出栈 */
int popStack(stackInfo *pS, ElemType *val)
{
    if ((NULL == pS) || (NULL == val))
    {
        printf("pStack point NULL or val point NULL\n");
        return -1;
    }
    
    if (pS->top <= 0)
    {
        printf("pStack empty\n");
        return -1;
    }
    
    pS->top--;
    memcpy(val, &pS->pData[pS->top], sizeof(ElemType));
    
    return 0;
}
/* 获取栈顶数据 */
int topStack(stackInfo *pS, ElemType *val)
{
    if ((NULL == pS) || (NULL == val))
    {
        printf("pStack point NULL or val point NULL\n");
        return -1;
    }

    if (0 >= pS->top)
    {
        printf("pStack empty\n");
        return -1;
    }
    
    memcpy(val, &pS->pData[pS->top - 1], sizeof(ElemType));
    
    return 0;
}
/* 计算栈中有效数据长度 */
int lengthOfStack(stackInfo *pS, unsigned int *val)
{
    if ((NULL == pS) || (NULL == val))
    {
        printf("pStack point NULL or val point NULL\n");
        return -1;
    }
    
    *val = pS->top;
    
    return 0;
}
/* 清空栈 */
int emptyStack(stackInfo *pS)
{
    if (NULL == pS)
    {
        printf("pStack point NULL\n");
        return -1;
    }
    
    while(pS->top)
    {
        /* 小技巧:如果赋值为0即0,如果赋值为FF,因16、32位平台的区别,鉴于可移植性考虑,赋值为0按位取反 */
        pS->top--;
    }

    return 0;
}
/* 销毁栈 */
int destoryStack(stackInfo **ppS)
{
    if (NULL == ppS)
    {
        printf("pStack point address is not exist\n");
        return -1;
    }
    
    if (NULL == *ppS)
    {
        printf("pStack point NULL\n");
        return -1;
    }

    emptyStack(*ppS);
    /* 关注点:1、两块动态内存需释放 2、注意释放的先后顺序 */
    while(1)
    free((*ppS)->pData);
    free(*ppS);

    return 0;
}
/* 拷贝栈
int copyStackElem(stackInfo *pSrcStack, stackInfo *pDestStack)
{
    if ((NULL == pSrcStack) || (NULL == pDestStack))
    {
        printf("copyStack pSrcStack or pDestStack point NULL\n");
        return -1;
    }

    pDestStack->top = pSrcStack->top;
    for (int i=0; i<pSrcStack->top; i++)
    {
        memcpy(&pDestStack->pData[i], &pSrcStack->pData[i], sizeof(ElemType));
    }

    return 0;
} */

/* 入口 */
ElemType currAddr = {0, 0};
/* 下一步 */
ElemType nextAddr = {0, 0};
/* 出口 */
ElemType escapeAddr = {4, 4};
/* 最大路标 */
ElemType maxWayAddr = {5, 5};
/* 最小路标 */
ElemType minWayAddr = {0, 0};
/* 迷宫:1为墙壁,0为路 */
int maze[5][5]=
{
    {0, 1, 0, 0, 0},
    {0, 1, 0, 1, 0},
    {0, 0, 0, 0, 0},
    {0, 1, 1, 1, 0},
    {0, 0, 0, 1, 0},
};
ElemType preDecessor[5][5] =
{
    {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}},
    {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}},
    {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}},
    {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}},
    {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}},
};
/* 更新一步 */
int visit(stackInfo *pS, ElemType *pCurrAddr, ElemType *pNextAddr)
{
    maze[pNextAddr->y][pNextAddr->x] = 2;
    preDecessor[pNextAddr->y][pNextAddr->x].x = pCurrAddr->x;
    preDecessor[pNextAddr->y][pNextAddr->x].y = pCurrAddr->y;
    pushStack(pS, pNextAddr);

    return 0;
}
/* 测试入口 */
int main(void)
{
    stackInfo *pNewStack = NULL;
    initStack(&pNewStack, 100);

    maze[currAddr.x][currAddr.y] = 2;
    pushStack(pNewStack, &currAddr);

    /* 保存每一步路径,有空闲空间可保存 */
    while(pNewStack->top != pNewStack->capacity)
    {
        popStack(pNewStack, &currAddr);
        if (   currAddr.x == escapeAddr.x
            && currAddr.y == escapeAddr.y)
        {
            break;
        }
        if (   currAddr.x + 1 < maxWayAddr.x
            && maze[currAddr.y][currAddr.x + 1] == 0)
        {
            nextAddr.x = currAddr.x + 1;
            nextAddr.y = currAddr.y;
            visit(pNewStack, &currAddr, &nextAddr);
        }
        if (   currAddr.y + 1 < maxWayAddr.y
            && maze[currAddr.y + 1][currAddr.x] == 0)
        {
            nextAddr.x = currAddr.x;
            nextAddr.y = currAddr.y + 1;
            visit(pNewStack, &currAddr, &nextAddr);
        }
        if (   currAddr.x - 1 >= minWayAddr.x
            && maze[currAddr.y][currAddr.x - 1] == 0)
        {
            nextAddr.x = currAddr.x - 1;
            nextAddr.y = currAddr.y;
            visit(pNewStack, &currAddr, &nextAddr);
        }
        if (   currAddr.y - 1 >= minWayAddr.y
            && maze[currAddr.y - 1][currAddr.x] == 0)
        {
            nextAddr.x = currAddr.x;
            nextAddr.y = currAddr.y - 1;
            visit(pNewStack, &currAddr, &nextAddr);
        }
        
        printf("print current position\n");
    }
    
    if (   currAddr.x == escapeAddr.x
        && currAddr.y == escapeAddr.y)
    {
        printf("(%d, %d)\n", currAddr.y, currAddr.x);
        while(preDecessor[currAddr.y][currAddr.x].y != -1)
        {
            currAddr = preDecessor[currAddr.y][currAddr.x];
            printf("(%d, %d)\n", currAddr.y, currAddr.x);
        }
    }
    else
    {
        printf("no find way\n");
    }

    return 0;    
}

转载于:https://www.cnblogs.com/tedani/p/9990729.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值