标签:算法
面试中常常会遇到算法的问题 而基础算法的考核离不开链表和二叉树,下面是对这两种数据结构常见问题的总结
#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;
}
#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