数据结构(面试)

看了剑指offer发现一个问题有好多种思路去解决,之前自己考虑的都太普遍性,应当多样化的来思考问题
最深体会:写出实现功能的代码,和写出优异的代码是两回事!
1.链表的倒叙打印
(1)是否可以改变链表结构,可以改变就改变以后打印
(2)不允许改变链表结构可以直接使用循环,但是时间复杂度会是O(n)
(3)使用栈来存储,那么就会简单很多,只需要O(n)的时间复杂度
(4)由递归和循环的关系不难想出其实递归也可以解决该问题
用栈解决的方案

void List::resStaShow()
{
    std::stack<Node*> s;
    int len = this->Getlength();
    Node* tmp = plist.next;
    for (int i = 0; i < len; ++i)
    {
        s.push(tmp);
        tmp = tmp->next;
    }
    while (!s.empty())
    {
        tmp = s.top();
        printf("%d \n", tmp->date);
        s.pop();
    }
}

2.重建二叉树
输入二叉树的前序遍历和中序遍历的,请重建出该二叉树。
12473568
47215386
代码如下,输出函数顺序是前序
本题重点
掌握递归思想,熟悉前序和中序关系
注意
我的代码只实现了两字符顺序匹配的情况,那么不匹配的时候应当如何呢?
应该加一个判断函数,判断这两个是否是合适的字符串
如果说根节点是NULL呢?
如果说是特殊的二叉树呢?

BinaryTreeNode* rebulit(int str1[], int str2[], int length)
{
    if (length == 0)
    {
        return NULL;
    }
    BinaryTreeNode* p = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
    p->m_nValue = str1[0];
    p->m_pLeft = NULL;
    p->m_pRight = NULL;
    if (length == 1)
    {
        return p;
    }

    int i = 0;
    for (i; i < length; ++i)//i=0
    {
        if (str2[i] == str1[0])
        {
            break;
        }
    }

    p->m_pLeft = rebulit(&str1[1], str2, i);
    if (i + 1 < length)
    {
        p->m_pRight = rebulit(&str1[ i + 1], &str2[i + 1], length - i - 1);
    }
    else
    {
        p->m_pRight = NULL;
    }
    return p;
}

void rebuiltTree(BinaryTreeNode **root, int str1[], int str2[], int length)
{
    *root = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
    (*root)->m_pLeft = NULL;
    (*root)->m_pRight = NULL;


    BinaryTreeNode* p = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
    p->m_nValue = str1[0];
    p->m_pLeft = NULL;
    p->m_pRight = NULL;

    (*root)->m_pLeft = p;//第一个结点放到根节点的左边

    int i = 0;
    for (i; i < length; ++i)//3
    {
        if (str2[i] == str1[0])
        {
            break;
        }
    }
    p->m_pLeft = rebulit(&str1[1], str2, i);
    if (i + 1 < length)
    {
        p->m_pRight = rebulit(&str1[ i + 1], &str2[ i + 1], length - i - 1);
    }
}

void Show(BinaryTreeNode *first)
{
    if (first == NULL)
    {
        return;
    }
    printf("%d ", first->m_nValue);
    Show(first->m_pLeft);
    Show(first->m_pRight);
}

3.两个栈实现队列(这里用的是C++懒得写栈)

#include <iostream>
#include <stack>
using namespace std;

class Queue
{
public:
    void push(int data)
    {
        p1.push(data);
    }

    int front()//这个函数想要加判断的,但是加的话必须返回一个值,所以就先暂定-1吧,因为我试了下系统的他貌似也是直接报错,让运行错误
    {
         if (p1.empty())
        {
            printf("队列为空无法提取\n");
            return -1;
        }
        change(&p1, &p2);
        int tmp = p2.top();
        change(&p2, &p1);//为了可以持续使用变换完了以后还得变回来
        return tmp;
    }

    void pop()//注意删除完了的判断
    {
        if (p1.empty())
        {
            printf("队列为空无法删除\n");
            return;
        }
        change(&p1, &p2);
        p2.pop();
        change(&p2, &p1);
    }
private:
    stack<int> p1;
    stack<int> p2;
    void change(stack<int> *p1, stack<int> *p2)//把p1的值完全放到p2
    {
        int tmp;
        while (!(*p1).empty())
        {
            tmp = (*p1).top();
            (*p2).push(tmp);
            (*p1).pop();
        }
    }
};


int main()
{
    Queue q;
    for (int i = 0; i < 10; ++i)
    {
        q.push(i);
    }

    for (int i = 0; i < 10; ++i)
    {
        cout << q.front() << endl;
        q.pop();
    }

    return 0;
}

相应的两个队列实现一个栈的思想其实是一样的,先进先出换成后进先出罢了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值