【面试】数据结构
来源:互联网 发布:天顶星人 知乎 编辑:程序博客网 时间:2024/05/22 05:25
单链表
先给出定义部分和相关调试部分
#include <bits/stdc++.h>using namespace std;struct ListNode{ int v; struct ListNode *next;}*head;ListNode* insert(int v){ ListNode* p=head; if(head == NULL) { head = new ListNode; head -> next = 0; head->v = v; return head; } while(p->next!=NULL) p = p->next; p -> next = new ListNode; p = p ->next; p->next = NULL; p -> v =v; return p;}void show(){ for(ListNode*p = head;p!=NULL;p=p->next) printf("%d ",p->v); puts("");}
单链表翻转
通过三个指针实现.
ListNode*rev(ListNode *head){ ListNode *p,*q,*t; ///保证最少有两个节点 if(head == NULL||head -> next == NULL) return head; p = NULL; q = head; t = head; while(t!=NULL) { t = t -> next; q->next = p; p = q; q = t; } return p;}
调试与验证
void showRev(){ head = NULL; show(); head = rev(head); show(); insert(1); show(); head = rev(head); show(); head = rev(head); insert(2); show(); head = rev(head); show(); head = rev(head); insert(3); show(); head = rev(head); show(); head = rev(head); insert(4); show(); head = rev(head); show(); head = rev(head);}
判环
定义两个指针,一个一次走两个,另一个一次走一个. 如果有环就会相遇
bool hasLoop(ListNode *head){ ListNode *p1 , *p2; p1 = p2 = head; while(NULL != p1 && NULL != p1 ->next) { p1 = p1 -> next; p1 = p1 -> next; p2 = p2 -> next; if(p1 == p2) return 1; } return 0;}
调试与验证
void showHasLoop1(){ ListNode *a , *b; head = NULL; show(); printf("ans:%d\n",hasLoop(head)); show(); a = insert(1); show(); printf("ans:%d\n",hasLoop(head)); show(); a -> next = head; printf("ans:%d\n",hasLoop(head));}void showHasLoop2(){ head = NULL; insert(1); insert(2); insert(3) -> next = head; printf("ans:%d\n",hasLoop(head));}void showHasLoop3(){ ListNode *a; head = NULL; insert(1); insert(2); a = insert(3); insert(4); insert(5); insert(6) -> next = a; printf("ans:%d\n",hasLoop(head));}
环长
先判环,如果有环,那么就一个指针移动,另一个不动,作为标记.
int circleLen(ListNode *head){ ListNode *p1 , *p2; p1 = p2 = head; int cnt=0; while(NULL != p1 && NULL != p1 ->next) { p1 = p1 -> next; p1 = p1 -> next; p2 = p2 -> next; if(p1 == p2) { p1 = p1 -> next; for(cnt = 1;p1 != p2;cnt ++) { p1 = p1 -> next; } break; } } return cnt;}
验证
void showCircleLen1(){ ListNode *a , *b; head = NULL; show(); printf("ans:%d\n",circleLen(head)); show(); a = insert(1); show(); printf("ans:%d\n",circleLen(head)); show(); a -> next = head; printf("ans:%d\n",circleLen(head));}void showCircleLen2(){ head = NULL; insert(1); insert(2); insert(3) -> next = head; printf("ans:%d\n",circleLen(head));}void showCircleLen3(){ ListNode *a; head = NULL; insert(1); insert(2); a = insert(3); insert(4); insert(5); insert(6) -> next = a; printf("ans:%d\n",circleLen(head));}
环前链长
还是定义两个指针,p1指针先走环长个节点,然后p1和p2步进,再次相遇的时候p2走的步数就是链长.需要注意的是没有环的情况.
int linkLen(ListNode *head){ int ret; int len = circleLen(head); ListNode *p1, *p2 ; p1 = p2 = head; for(int i = len; i ; i-- ) { p1 = p1 -> next; } for(ret = 0;p1 != p2 || (NULL != p1 && len == 0); ret++ ) { p1 = p1 -> next; p2 = p2 -> next; } return ret;}
验证
void showLinkLen1(){ ListNode *a , *b; head = NULL; show(); printf("ans:%d\n",linkLen(head)); show(); a = insert(1); show(); printf("ans:%d\n",linkLen(head)); show(); a -> next = head; printf("ans:%d\n",linkLen(head));}void showLinkLen2(){ head = NULL; insert(1); insert(2); insert(3) -> next = head; printf("ans:%d\n",linkLen(head));}void showLinkLen3(){ ListNode *a; head = NULL; insert(1); insert(2); a = insert(3); insert(4); insert(5); insert(6) -> next = a; printf("ans:%d\n",linkLen(head));}
全部代码
#include <bits/stdc++.h>using namespace std;struct ListNode{ int v; struct ListNode *next;}*head;ListNode* insert(int v){ ListNode* p=head; if(head == NULL) { head = new ListNode; head -> next = 0; head->v = v; return head; } while(p->next!=NULL) p = p->next; p -> next = new ListNode; p = p ->next; p->next = NULL; p -> v =v; return p;}void show(){ for(ListNode*p = head;p!=NULL;p=p->next) printf("%d ",p->v); puts("");}ListNode*rev(ListNode *head){ ListNode *p,*q,*t; ///保证最少有两个节点 if(head == NULL||head -> next == NULL) return head; p = NULL; q = head; t = head; while(t!=NULL) { t = t -> next; q->next = p; p = q; q = t; } return p;}void showRev(){ head = NULL; show(); insert(1); show(); head = rev(head); show(); head = rev(head); insert(2); show(); head = rev(head); show(); head = rev(head); insert(3); show(); head = rev(head); show(); head = rev(head); insert(4); show(); head = rev(head); show(); head = rev(head);}bool hasLoop(ListNode *head){ ListNode *p1 , *p2; p1 = p2 = head; while(NULL != p1 && NULL != p1 ->next) { p1 = p1 -> next; p1 = p1 -> next; p2 = p2 -> next; if(p1 == p2) return 1; } return 0;}void showHasLoop1(){ ListNode *a , *b; head = NULL; show(); printf("ans:%d\n",hasLoop(head)); show(); a = insert(1); show(); printf("ans:%d\n",hasLoop(head)); show(); a -> next = head; printf("ans:%d\n",hasLoop(head));}void showHasLoop2(){ head = NULL; insert(1); insert(2); insert(3) -> next = head; printf("ans:%d\n",hasLoop(head));}void showHasLoop3(){ ListNode *a; head = NULL; insert(1); insert(2); a = insert(3); insert(4); insert(5); insert(6) -> next = a; printf("ans:%d\n",hasLoop(head));}int circleLen(ListNode *head){ ListNode *p1 , *p2; p1 = p2 = head; int cnt=0; while(NULL != p1 && NULL != p1 ->next) { p1 = p1 -> next; p1 = p1 -> next; p2 = p2 -> next; if(p1 == p2) { p1 = p1 -> next; for(cnt = 1;p1 != p2;cnt ++) { p1 = p1 -> next; } break; } } return cnt;}void showCircleLen1(){ ListNode *a , *b; head = NULL; show(); printf("ans:%d\n",circleLen(head)); show(); a = insert(1); show(); printf("ans:%d\n",circleLen(head)); show(); a -> next = head; printf("ans:%d\n",circleLen(head));}void showCircleLen2(){ head = NULL; insert(1); insert(2); insert(3) -> next = head; printf("ans:%d\n",circleLen(head));}void showCircleLen3(){ ListNode *a; head = NULL; insert(1); insert(2); a = insert(3); insert(4); insert(5); insert(6) -> next = a; printf("ans:%d\n",circleLen(head));}int linkLen(ListNode *head){ int ret; int len = circleLen(head); ListNode *p1, *p2 ; p1 = p2 = head; for(int i = len; i ; i-- ) { p1 = p1 -> next; } for(ret = 0;p1 != p2 || (NULL != p1 && len == 0); ret++ ) { p1 = p1 -> next; p2 = p2 -> next; } return ret;}void showLinkLen1(){ ListNode *a , *b; head = NULL; show(); printf("ans:%d\n",linkLen(head)); show(); a = insert(1); show(); printf("ans:%d\n",linkLen(head)); show(); a -> next = head; printf("ans:%d\n",linkLen(head));}void showLinkLen2(){ head = NULL; insert(1); insert(2); insert(3) -> next = head; printf("ans:%d\n",linkLen(head));}void showLinkLen3(){ ListNode *a; head = NULL; insert(1); insert(2); a = insert(3); insert(4); insert(5); insert(6) -> next = a; printf("ans:%d\n",linkLen(head));}int main(){ showLinkLen3();}
堆
定义和性质:
- 二叉堆是完全二叉树
- 父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值
- 每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)
(以下例子使用大根堆)
建立(维护)
- 按倒序扫一遍父节点
- 对于每个父节点找到最大的一个子节点,若该节点严格大于父节点,则交换父子的值,再对该节点递归的进行第二步,直到没有子节点大于父节点,此时继续执行第一步.
思考:当我们执行第 2 步的时候,我们就是在维护这个子堆的性质.假如 子堆A 满足性质,那么这个 子堆A 的 父节点B 一定能在少于 logn 次交换后,使子堆 A∪B 满足堆的性质.
插入
把要插入的数当成堆的最后一个元素,要维护堆把该节点与父节点进行交换,递归执行,直到满足堆的性质(该节点严格小于父节点)
删除
大根堆规定只能删除最大元素,也就是头结点.步骤如下:
- 移除头结点
- 将最后一个节点换到头部(代码中是 1,2 步结合,将头结点与最后一个节点置换,然后长度 -1 )
- 执行建立时第 2 步操作,维护堆的性质
排序
利用大根堆的性质,每次可以删除最大的元素,我们把这个元素放在队列最后不去考虑他,递归执行找第 n-i 大的元素放在队列尾部.这样就形成了一个非递减数列.
代码
#include <bits/stdc++.h>using namespace std;const int MAXN = 1e5;///BigRootstruct heap{ int A[MAXN] , n; void init(int _n , int m) { n = _n; srand(time(NULL)); for(int i=0;i<n;i++) A[i] = rand() % m; } void show() { for(int i=0;i<n;i++) printf("%d ",A[i]); puts(""); } int getLs(int num) { return ( ( num + 1 ) << 1 ) - 1; } int getRs(int num) { return ( num + 1 ) << 1 ; } int getF(int num) { return ( num - 1 ) >> 1; } void _fixDown(int num) { while(num<n) { int ls = getLs(num) , rs = getRs(num); printf("\t%d %d\n",ls,rs); int m ; if (ls >= n) break; else if ( rs >= n) m = ls; else m = ( A[ls] < A[rs] ? rs : ls ); if( A[num] < A[m] ) { printf("\tswap(%d,%d)\n",num,m); swap(A[num],A[m]); num = m; } else break; } } void build() { for(int i = getF(n) ; i >= 0 ; i-- ) printf("B:%d\n",i), _fixDown(i); } void insert(int v) { int num = n; A[n++] = v; int f; while(num && A[num] > A[ f = getF(num) ] ) { printf("\tswap(%d,%d)\n",num,f); swap(A[num] , A[f]); num = f; } } void remove() { n--; printf("\tswap(%d,%d)\n",n,0); swap( A[n] , A[0] ); _fixDown(0); } void sort() { int _n = n; build(); while(n) remove(); n = _n; }}h;char hit[10000];int offset = 0;void pt(char *s){ sprintf(hit+offset,s); offset += strlen(s);}int AT[] = {2,1,6,1,2,2,6,2,8,5};int main(){ pt("i v\tinsert(v)\n"); pt("r\tremove()\n"); pt("p\tprint()\n"); pt("s\tsort()\n"); pt("h\thelp()\n"); h.init(10,10); memcpy(h.A,AT,sizeof(AT)); h.show(); h.build(); h.show(); char op[5]; while(scanf("%s",op)!= EOF) { int v; switch (op[0]) { case 'i': scanf("%d",&v); h.insert(v); break; case 'r': h.remove(); break; case 'p': h.show(); break; case 's': h.sort(); break; case 'h': puts(hit); break; case 'q': return 0; } } return 0;}
1 0
- 数据结构面试
- 【面试】数据结构
- 数据结构面试
- 数据结构(面试)
- 《面试》数据结构
- 整理:数据结构面试大全
- 数据结构面试大全
- 数据结构面试大全
- 数据结构面试大全
- 微软 数据结构面试题目
- 面试 数据结构 算法
- 数据结构面试大全
- 数据结构面试大全
- 微软数据结构算法 面试
- 数据结构 算法 编程 面试
- 整理:数据结构面试大全
- [面试准备】数据结构--链表
- 【面试准备】数据结构-队列
- python show-me-the-code 第0011题
- 使用Eclipse时一些报错
- 友盟与听云比较
- 事实上,最糟的并不是李世石完败AlphaGo......
- HDU 5521 15年亚洲赛现场题目 图论之最短路
- 【面试】数据结构
- hdu3339 In Action(floyd+背包)
- BZOJ1877晨跑
- 学习Jave的第一步:JDK的安装和变量配置
- Struts2拦截器实现异常处理机制
- 阿尔法狗 4:1大胜人类冠军后,也重新定义了人类
- WAMPServer自定义根目录
- 试编写一个程序,输入一个字符串,统计其中有多少各单词?单词之间用空格分开
- 开关按钮的实现