码迷,mamicode.com
首页 > 编程语言 > 详细

面试之常用算法总结

时间:2015-04-11 00:02:16      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:算法

面试中常常会遇到算法的问题 而基础算法的考核离不开链表和二叉树,下面是对这两种数据结构常见问题的总结

1、链表

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

/*
    链表的总结 插入 删除以及遍历 
    以及链表相关的应用 
*/

// 链表的结构

// 插入 若第一个节点为空则需啊替换 所以传递的参数必须是指针的指针 否则修改无效

struct ListNode{
    int m_value;
    ListNode *m_pNext;
};


void addToTail(ListNode **pHead,int value)
{
        ListNode *pNew=new ListNode();
        pNew->m_value=value;
        pNew->m_pNext=NULL;
        if(*pHead==NULL)
        {
            * pHead=pNew;
            printf("%d ",(*pHead)->m_value);
        }else{

            ListNode *pNode=*pHead;
            while(pNode->m_pNext!=NULL )
            {
                pNode=pNode->m_pNext;
            }    
            pNode->m_pNext=pNew;
            printf("%d ",pNode->m_pNext->m_value);
        } 


} 

// 删除链表中 指定值的节点

void RemoveNode(ListNode **pHead,int value)
{
    if(*pHead==NULL || pHead==NULL)
    {
        return ;
    }

    ListNode *pTODeleted=NULL;
    if( (*pHead)->m_value==value )
    {
        pTODeleted=*pHead;
        *pHead=(*pHead)->m_pNext;
    }else{

        ListNode *pNode=*pHead;
        while(pNode->m_pNext!=NULL && pNode->m_pNext->m_value!=value)
        {
            pNode=pNode->m_pNext;
        }

        if(pNode->m_pNext!=NULL && pNode->m_pNext->m_value==value)
        {
            pTODeleted=pNode->m_pNext;
            pNode->m_pNext=pNode->m_pNext->m_pNext;
        }    

    }

    if(pTODeleted!=NULL)
    {
        delete pTODeleted;
        pTODeleted=NULL;

    }
} 

// 从尾到头打印链表 两种方法 一种是使用递归 一种是使用栈 

// 递归 
void printListNodeInvertedByRecursion(ListNode *pNode)
{

    if(pNode!=NULL)
    {
        printListNodeInvertedByRecursion(pNode->m_pNext);
         printf("%d ",pNode->m_value); 
    }

} 

// 栈
void printListNodeInvertedByStack(ListNode *pNode)
{
    std::stack<ListNode*> nodes;

    while(pNode!=NULL)
    {
        nodes.push(pNode);
        pNode=pNode->m_pNext;
    }

    while(!nodes.empty())
    {
        ListNode *node=nodes.top();
        printf("%d ",node->m_value);
        nodes.pop();
    }
}

/* 在O(1)时间内删除链表节点
    问题:给定单向链表的头指针和一个节点指针 定义一个函数在O(1)时间内删除该节点
    链表节点与函数定义如下:
    struct ListNode
    {
        int m_value;
        ListNode *m_pNext;
    };

    void DeletedNode(ListNode **pListHead,ListNode *pToDeleted); 

*/ 

void DeletedNode(ListNode **pListHead,ListNode *pToDeleted)
{

    if(!pListHead || !pToDeleted)
    {
        return;    
    }
    // 删除节点不是尾节点 
    if(pToDeleted->m_pNext !=NULL)
    {
        ListNode *temp=pToDeleted->m_pNext;
        pToDeleted->m_pNext=temp->m_pNext;
        pToDeleted->m_value=temp->m_value;
        delete temp;
        temp=NULL;

    }else{
        // 只有一个节点 
        if(*pListHead==pToDeleted)
        {
            delete pToDeleted;
            pToDeleted=NULL;
            *pListHead=NULL;
        }else{
            // 删除节点是尾节点 
            ListNode *pNode=*pListHead;
            while(pNode->m_pNext!=pToDeleted)
            {
                pNode=pNode->m_pNext;

            }

            pNode->m_pNext=NULL;
            delete pToDeleted;
            pToDeleted=NULL;

        }


    }

} 


/*
    链表中倒数第k个节点

    解析:使用两个指针,一个指针先走k个节点,另一个指针指向头指针,
    然后一起往下遍历,当后一个指针指向尾指针时,前一个指针就是倒数第k个指针 

*/ 

ListNode *FindkthToTail(ListNode *pListHead,unsigned int k)
{

    if(pListHead==NULL || k==0)
    {
        return NULL;
    }

    ListNode *pHead=pListHead;
    ListNode *pBehind = NULL;
    for(unsigned int i=0;i<k-1;i++)
    {
        if(pHead->m_pNext!=NULL)
        {
            pHead=pHead->m_pNext;
        }else{
            return NULL;
        }
    }

    pBehind=pListHead;
    while(pHead->m_pNext!=NULL)
    {
        pHead=pHead->m_pNext;
        pBehind=pBehind->m_pNext;
    }

    return pBehind;
} 

/*
    反转链表 

    解法:在遍历链表的工程中修改next指向的节点 并将最后一个节点保存为头节点 
*/

 ListNode *ReverseList(ListNode *pListHead)
{
    ListNode *pReverseHead=NULL;
    ListNode *pNode=pListHead;
    ListNode *pPrev=NULL;
    while(pNode!=NULL)
    {
        ListNode *pNext=pNode->m_pNext;
        if(pNext==NULL)
        {
            pReverseHead=pNode;
        }

       pNode->m_pNext=pPrev;

       pPrev=pNode;
       pNode=pNext; 
    }

    return pReverseHead;
} 


/*
    合并两个排序链表
    题目;输入两个递增排列的链表,合并这两个链表并使新链表中的节点仍然是按照递增排序的。 
    解析:递归 
*/

ListNode *Merge(ListNode *pHead1,ListNode *pHead2)
{
    if(pHead1==NULL)
    {
        return pHead2;
    }else if(pHead2==NULL)
    {
        return pHead1;
    }

    ListNode *pMergeHead=NULL;

    if(pHead1->m_value > pHead2->m_value)
    {
        pMergeHead=pHead2;
        pMergeHead->m_pNext=Merge(pHead1,pHead2->m_pNext);

    }else{

        pMergeHead=pHead1;
        pMergeHead->m_pNext=Merge(pHead1->m_pNext,pHead2);
    }

    return pMergeHead;

} 
int main()
{
    ListNode *pHead=NULL;
    for(int i=0;i<10;i++)
    {
        addToTail(&pHead,i);
    }

    putchar(‘\n‘);
    printListNodeInvertedByRecursion(pHead);
    RemoveNode(&pHead,9);
    putchar(‘\n‘);
    printListNodeInvertedByStack(pHead);
    putchar(‘\n‘);
    system("pause");      
    return 0;    
}



2.二叉树

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<Stack>
#include<Queue>
#include<vector>
/*
  重建二叉树 根据前序遍历和中序遍历 建立二叉树 
*/ 


struct BinaryTreeNode
{
  int m_value;
  BinaryTreeNode *m_pLeft;
  BinaryTreeNode *m_pRight;

}; 


// 异常终止函数 到此,当出现异常的时候,
//程序是终止了,但是我们并没有捕获到异常信息,
//要捕获异常信息,我们可以使用注册终止函数atexit(),它的原型是这样的:int atexit(atexit_t func);

void Exception()
{
 printf("Invalid Input");
} 

// 根据前序遍历和中序遍历 构建二叉树
BinaryTreeNode *ConstructCore(int *startPreorder,int *endPreorder,int *startInorder,int *endInorder);
BinaryTreeNode* ConstructTree(int *preorder,int *inorder,int length)
{
     if(preorder==NULL || inorder==NULL || length<=0)
     {
        return NULL;
     }    

     BinaryTreeNode *treeHead=ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
     return treeHead;          
} 


BinaryTreeNode *ConstructCore(int *startPreorder,int *endPreorder,int *startInorder,int *endInorder)
{
     int rootValue=startPreorder[0];
     BinaryTreeNode *root=new BinaryTreeNode();
     root->m_value=rootValue;
     root->m_pLeft=root->m_pRight=NULL;

     // 遍历到了最底层 返回叶子节点 
     if(startPreorder == endPreorder)
     {
         if(startInorder==endInorder && *startInorder==*endInorder)
         {
            return root;
         }else{
               //throw exception("Invalid Input");    
               atexit(Exception);  
         }                    
     }

     int *rootInorder=startInorder;

     while(*rootInorder!=rootValue)
     {
         rootInorder++;
     }

     if(rootInorder==endInorder && *rootInorder!=rootValue)
     {
       //throw std::exception("Invalid Input");
       atexit(Exception);
     }

     int leftLen=rootInorder-startInorder;
     int *leftPreorderEnd=startPreorder+leftLen;

     if(leftLen>0)
     {
        root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
     }
     if(leftLen<endPreorder-startPreorder)
     {
         root->m_pRight=ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
     }


     return root;
}

// 前序遍历

void preorderTraverse(BinaryTreeNode *treeNode)
{
     if(treeNode==NULL)
     {
        return;
     }

     printf("%d ",treeNode->m_value);
     if(treeNode->m_pLeft!=NULL);
     preorderTraverse(treeNode->m_pLeft);

     if(treeNode->m_pRight!=NULL)
     preorderTraverse(treeNode->m_pRight);

} 

// 中序遍历
void inorderTraverse(BinaryTreeNode *treeNode)
{

     if(treeNode->m_pLeft!=NULL)
     {
        inorderTraverse(treeNode->m_pLeft);
     }

     printf("%d ",treeNode->m_value);


     if(treeNode->m_pRight!=NULL)
     {
            inorderTraverse(treeNode->m_pRight);                          
     }


}



// 后序遍历 
void postorderTraverse(BinaryTreeNode *treeNode)
{

     if(treeNode->m_pLeft!=NULL)
     {
        postorderTraverse(treeNode->m_pLeft);
     }

     if(treeNode->m_pRight!=NULL)
     {
         postorderTraverse(treeNode->m_pRight);                          
     }

     printf("%d ",treeNode->m_value);

}


// 宽度遍历 使用队列 

void BFS(BinaryTreeNode *root)
{
     // TODO
     std::queue<BinaryTreeNode *> treeNodes;
     treeNodes.push(root);

     BinaryTreeNode *node;
     while(!treeNodes.empty())
     {
        node=treeNodes.front();
        printf("%d ",node->m_value);
        treeNodes.pop();
        if(node->m_pLeft!=NULL)
        {
            treeNodes.push(node->m_pLeft);
        }

         if(node->m_pRight!=NULL)
        {
            treeNodes.push(node->m_pRight);
        }
     }

} 

// 深度遍历 使用栈 
void DFS(BinaryTreeNode *root)
{
     std::stack<BinaryTreeNode *> treeNodes; 

     treeNodes.push(root);
     BinaryTreeNode *node;
     while(!treeNodes.empty())
     {
        node=treeNodes.top();
        printf("%d ",node->m_value);
        treeNodes.pop();
        if(node->m_pRight!=NULL)
        {
          treeNodes.push(node->m_pRight);
        }

        if(node->m_pLeft!=NULL)
        {
          treeNodes.push(node->m_pLeft);
        }
     } 
}

/* 树的子结构
    题目:输入两棵二叉树A和B,判断B是否是A的子结构

    解析:分两步解决该问题,首先在A中寻找 和B头节点相同的节点 
    然后比较这些节点组成子结构是否和B相同 
*/

bool DosTree1HasTree2(BinaryTreeNode *pRoot1,BinaryTreeNode *pRoot2)
{
    if(pRoot2==NULL)
    {
        return true;
    }

    if(pRoot1==NULL)
    {
        return false;
    }

    if(pRoot1->m_value!=pRoot2->m_value)
    {
        return false;
    }

    return DosTree1HasTree2(pRoot1->m_pLeft,pRoot2->m_pLeft) &&
    DosTree1HasTree2(pRoot1->m_pRight,pRoot2->m_pRight);

}
bool HasSubtree(BinaryTreeNode *pRoot1,BinaryTreeNode *pRoot2)
{
    bool result=false;
    if(pRoot1!=NULL && pRoot2!=NULL)
    {
        if(pRoot1->m_value == pRoot2->m_value)
        {
            result=DosTree1HasTree2(pRoot1,pRoot2); 
        }

        if(!result)
        {
            result=HasSubtree(pRoot1->m_pLeft,pRoot2);
        }
        if(!result)
        {
            result=HasSubtree(pRoot1->m_pRight,pRoot2);
        }

    }


    return result;

}

/*
    二叉树的镜像 
*/

void MirrorRecursively(BinaryTreeNode *pRoot)
{
    if(pRoot==NULL)
    {
        return ;
    }
    if(pRoot->m_pLeft==NULL && pRoot->m_pRight==NULL)
    {
        return ;
    }

    BinaryTreeNode *temp=pRoot->m_pLeft;
    pRoot->m_pLeft=pRoot->m_pRight;
    pRoot->m_pRight=temp;

    if(pRoot->m_pLeft)
    {
        MirrorRecursively(pRoot->m_pLeft);
    }

    if(pRoot->m_pRight)
    {
        MirrorRecursively(pRoot->m_pRight);
    }

}



/*
    题目:求二叉树中和为某一值得路径
    输入一个二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 

*/

void FindPath(BinaryTreeNode *pRoot,int expectedSum,std::vector<int> &path,int currentSum)
{
    currentSum+=pRoot->m_value;
    path.push_back(pRoot->m_value);
    bool isLeaf=pRoot->m_pLeft==NULL &pRoot->m_pRight==NULL;

    if(currentSum== expectedSum && isLeaf)
    {
        printf("\nLJ is found!\n");
        std::vector<int>::iterator iter=path.begin();
        for(;iter!=path.end();++iter)
        {
            printf("%d\t",*iter);
        }

    }

     if(pRoot->m_pLeft!=NULL && currentSum<expectedSum)
    {
         FindPath(pRoot->m_pLeft,expectedSum,path,currentSum);
    }

    if(pRoot->m_pRight!=NULL && currentSum<expectedSum)
    {
         FindPath(pRoot->m_pRight,expectedSum,path,currentSum);
    }

    path.pop_back();


}
void FindPath(BinaryTreeNode *pRoot,int expectedSum)
{
    if(pRoot==NULL)
    {
        return ;
    }
    std::vector<int> path;
    int currentSum=0;
    FindPath(pRoot,expectedSum,path,currentSum);

}




int main()
{
    int a[8]={1,2,4,7,3,14,6,8};
    int b[8]={4,7,2,1,14,3,8,6};

    BinaryTreeNode *treeNode=ConstructTree(a,b,8);
    if(treeNode!=NULL)
    {
        preorderTraverse(treeNode);
        putchar(‘\n‘);
        inorderTraverse(treeNode);
        putchar(‘\n‘);
        postorderTraverse(treeNode);
    }

    printf("\nBFS: ");
    BFS(treeNode);
    printf("\nDFS: ");
    DFS(treeNode);
    FindPath(treeNode,18);
    printf("\n");
    system("pause  ");

    return 0;    
}

面试之常用算法总结

标签:算法

原文地址:http://blog.csdn.net/aehaojiu/article/details/44986499

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!