单链表经典面试题
来源:互联网 发布:老九门 网络销售价格 编辑:程序博客网 时间:2024/06/07 11:01
面试官通过考察应聘者的编程语言、数据结构和算法来判断应聘者是否具备扎实的基础知识。而单链表又是数据结构中最基本的知识。
1单链表总结
单链表的使用总是围绕着增、删、改、查结点等。其中,增加结点是最常用到的。归纳一下,常见有下面几种情况:
a.在首结点之前插入新结点
b.在尾结点之前插入新结点
c.在某个中间结点之前插入新结点
d.在某个中间结点之后插入新结点
/*链表结构定义*/typedef struct list_node{ int data; struct list_node *next;}list_node_t, link_list_t;1.1在首结点p之前插入s(头插法),且p一直作为首结点:(结点p作为一种游标)
操作:
s->next = p;p = s;
示例:采用头插法创建不带头结点的单链表。
int link_list_create(link_list_t **link_list, int n){ int i = 0; list_node_t *node = NULL;/*新生成的结点*/ list_node_t *cursor = NULL;/*游标结点*/ /*分配第一个结点*/ cursor = (list_node_t *)malloc(sizeof(list_node_t)); if (cursor == NULL) return -1; cursor->next = NULL; /*让*link_list指向第一个结点*/ *link_list = cursor; /*分配第2个结点至第n个结点*/ for (i = 1; i < n; i++) { node = (list_node_t *)malloc(sizeof(list_node_t)); if (node == NULL) return -1; /*头插法*/ node->next = cursor; cursor = node; } return 0;}
1.2在尾结点p之后插入s(尾插法),且p一直作为尾结点:(结点p作为一种游标)
操作:
p->next = s;p = s;
示例:采用尾插法创建不带头结点的单链表。
int link_list_create(link_list_t **link_list, int n){ int i = 0; list_node_t *node = NULL;/*新生成的结点*/ list_node_t *cursor = NULL;/*游标结点*/ /*分配第一个结点*/ cursor = (list_node_t *)malloc(sizeof(list_node_t)); if (cursor == NULL) return -1; cursor->next = NULL; /*让*link_list指向第一个结点*/ *link_list = cursor; /*分配第2个结点至第n个结点*/ for (i = 1; i < n; i++) { node = (list_node_t *)malloc(sizeof(list_node_t)); if (node == NULL) return -1; node->next = NULL; /*尾插法*/ cursor->next = node; cursor = node; } return 0;}
1.3在结点p之后插入s:(结点p只是链表中的任意一个结点)
操作:
s->next = p->next;p->next = s;
示例:在第i个位置上插入新结点,即在第i-1位置之后插入新结点
/*在第i个位置上插入新结点,i的范围为[1, list_len+1]*/int link_list_insert(link_list_t **link_list, int i, int data){ int j = 1; list_node_t *s = NULL; list_node_t *p = *link_list; if (*link_list == NULL || i < 0) { return -1; } /* *在第1个位置插入新结点,使得该结点成为第1个位置的结点 *对插入到第一个位置的结点需要特殊处理,这是不带头结点的缺点 */ if (i == 1) { s = (list_node_t *)malloc(sizeof(list_node_t)); if (s == NULL) return -1; s->data = data; /*插入到第1个位置*/ s->next = *link_list; *link_list = s; } else { /*找到第i-1个位置上的结点p*/ while (p && j < i - 1) { p = p->next; j++; } /*i大于链表的长度+1*/ if (!p) { return -1; } s = (list_node_t *)malloc(sizeof(list_node_t)); if (s == NULL) return -1; s->data = data; s->next = NULL; /*在结点p之后插入新结点s*/ s->next = p->next; p->next = s; } return 0;}
1.4在节点p之前插入s:(结点p只是链表中的任意一个结点)
操作:
s->next = p;/*s的下一个结点为p*/*last = s; /*修改q->next的值为s,即q的下一个结点为s*/说明:P = q->next;/*假设p的前一个结点为q*/node_t **last;/*声明二级指针last,指向p的前一个结点q的指针域next的地址*/last = &q->next;
示例:
/*在第i个位置之前插入新结点,i的范围为[1, list_len]*/int link_list_insert1(link_list_t **link_list, int i, int data){ int j = 0; list_node_t *s = NULL; list_node_t *p = NULL; list_node_t **last = NULL; if (*link_list == NULL || i < 0) { return -1; } last = link_list; p = *last; /*找到第i个位置上的结点p*/ while (p && j < i - 1) { last = &p->next;/*last为p的前一个结点的指针域的地址*/ p = p->next; j++; } /*i大于链表的长度*/ if (!p) { return -1; } /*生成新的结点s*/ s = (list_node_t *)malloc(sizeof(list_node_t)); if (s == NULL) return -1; s->data = data; /*在第i个位置之前插入s*/ s->next = p; *last = s; return 0;}
2单链表面试题
2.1求单链表中结点的个数
int list_node_num(link_list_t *link_list){ int num = 0; list_node_t *node = link_list; while (node) { ++num; node = node->next; } return num;}
2.2将单链表反转(即逆序排列)
/*功能:将单链表逆序 *说明: * 遍历原单链表,每遍历一个结点,则将其摘除,并 * 用头插法的方式,插入到新链表的头部。 *注意: 链表为空或只有一个结点的情况 */link_list_t *link_list_reverse(link_list_t *link_list){ list_node_t *next = NULL; link_list_t *link_rev_head = NULL;/*逆序链表的首结点*/ list_node_t *node = link_list; /*原链表的第一个结点*/ /*包含了原链表为空或只有一个结点的处理*/ while (node) { next = node->next;/*摘除结点node*/ node->next = link_rev_head;/*头插法,插入到新链表的头部*/ link_rev_head = node; node = next; /*下一个结点*/ } return link_rev_head;}
2.3查找单链表中倒数第K个结点(K>0)
/*功能:查找单链表中倒数第K个结点(k > 0) * *思路: * 使用两个指针,第一个指针先走K-1步,然后两个指针一起走。 * 当第一个指针走到尾结点的时候,第二个指针指向的就是倒数 * 第K个结点。 * 即: 正数第K个结点到末尾结点的距离等于 * 第1个结点到倒数第K个结点的距离。 * *注意: 链表为空的情况、K小于1或大于链表长度的情况 * */list_node_t *link_list_find_backward(link_list_t *link_list, int k){ int i = 0; list_node_t *node = link_list; list_node_t *k_node = link_list; /*输入错误处理*/ if (link_list == NULL) { return NULL; } /*查找链表第K个结点*/ while (node && --k) { node = node->next; } /*k大于链表长度或小于1*/ if (!node || k < 0) { return NULL; } /*查找链表倒数第K个结点*/ while (node->next) { node = node->next; k_node = k_node->next; } return k_node;}
2.4查找单链表的中间结点
/*功能: 查找单链表的中间结点 *思路: 与查找倒数第K个结点类似,两个问题一起问时,考察学习迁移能力。 * 使用两个指针,快指针每次走两步,慢指针每次走一步。 * 当快指针走到尾结点时,慢指针刚好走到中间结点 * *注意: 链表为空或只有一个或两个结点的情况 */list_node_t *link_list_find_middle(link_list_t *link_list){ list_node_t *fast_node = link_list;/*快指针,走两步*/ list_node_t *slow_node = link_list;/*慢指针,走一步*/ /*没有结点或只有一个结点*/ if (link_list == NULL || link_list->next == NULL) { return link_list; } /*保证fast_node是最后那个结点*/ while (fast_node->next) { /*fast_node走两步*/ fast_node = fast_node->next; if (fast_node->next) { fast_node = fast_node->next; } /*slow_node走一步*/ slow_node = slow_node->next; } return slow_node;}
2.5从尾到头打印单链表
/*功能:从尾到头打印单链表 *思路: * 颠倒顺序的问题,一般利用递归,让系统使用栈。 * */void link_list_print_reverse(link_list_t *link_list){ if (link_list == NULL) { return ; } else { link_list_print_reverse(link_list->next); printf("%d ", link_list->data); } return ;}
2.6将有序的两个单链表合并成一个新的依然有序的链表
link_list_t *link_list_merge(link_list_t *a_link_list, link_list_t *b_link_list){ link_list_t *link_list = NULL;/*新链表*/ list_node_t *node = NULL;/*游标结点*/ /*对新链表的第一个结点的特殊处理*/ if (a_link_list->data <= b_link_list->data) { link_list = a_link_list; a_link_list = a_link_list->next; } else { link_list = b_link_list; b_link_list = b_link_list->next; } node = link_list; node->next = NULL; while (a_link_list && b_link_list) { if (a_link_list->data <= b_link_list->data) { node->next = a_link_list; a_link_list = a_link_list->next; } else { node->next = b_link_list; b_link_list = b_link_list->next; } node = node->next; node->next = NULL; } /*插入剩余的链表段*/ node->next = (a_link_list ? a_link_list : b_link_list); return link_list;}
2.7判断一个单链表是否有环,若有环,求出进入环中的第一个结点
/*功能: 单链表是否存在环,若存在,则求进入环的第一个结点 *思路: *1 判断是否有环: * 使用两个指针,一个走两步,一个走一步。如果有环, * 则将在环中的的某个结点相遇。 *2 求进入环的第一个结点: * 碰撞点到连接点的距离等于第一个结点到连接点的距离。 * *注意:链表为空或只有一个结点(有环或没环)的情况, */list_node_t *link_list_loop_node(link_list_t *link_list){ list_node_t *fast_node = link_list; list_node_t *slow_node = link_list; /*链表为空*/ if (link_list == NULL) { return NULL; } /*判断是否有环*/ while (fast_node && fast_node->next) { fast_node = fast_node->next->next; slow_node = slow_node->next; if (fast_node == slow_node) { /*存在环,此时fast_node为碰撞点*/ break; } } /*不存在环*/ if (fast_node == NULL || fast_node->next == NULL) { return NULL; } /*求出进入环的第一个结点*/ slow_node = link_list; while (slow_node != fast_node) { slow_node = slow_node->next; fast_node = fast_node->next; } return slow_node;}
2.8判断两个单链表是否相交,若相交,求出相交的第一个结点
/*功能:判断两个单链表是否相交,若相交,则求相交的第一个结点 *思路: *1 判断是否相交: 两个单链表相交,则最后的结点相同 *2 求相交的第一个结点: * 计算链表1的长度LEN1,链表2的长度LEN2,计算长度差LEN = |LEN1 - LEN2| * 长度较长的链表先遍历LEN个结点,接着两个链表到第一个结点的长度 * 就相同了,再同时遍历。 */list_node_t *link_list_intersect(link_list_t *a_link_list, link_list_t *b_link_list){ int len = 0; int a_len = 0; int b_len = 0; list_node_t *node = NULL; list_node_t *a_node = a_link_list; list_node_t *b_node = b_link_list; if (a_link_list == NULL || b_link_list == NULL) { return NULL; } while (a_node->next) { a_node = a_node->next; a_len++; } while (b_node->next) { b_node = b_node->next; b_len++; } /*链表不相交则直接返回*/ if (a_node != b_node) { return NULL; } a_node = a_link_list; b_node = b_link_list; /*长度较长的链表先遍历到与较短的链表等长*/ if (a_len > b_len) { len = a_len - b_len; while (len--) { a_node = a_node->next; } } else { len = b_len - a_len; while (len--) { b_node = b_node->next; } } /*等长情况下,两个链表同时遍历,结点相同处便是相交点*/ while (a_node != b_node) { a_node = a_node->next; b_node = b_node->next; } return a_node;}
0 0
- 单链表经典面试题
- 【经典面试题】翻转单链表
- 单链表的一些经典面试题
- 经典面试题之逆序打印单链表
- IBM经典面试题
- 经典面试题
- java经典面试题
- 经典面试题
- Java经典面试题
- 经典C++面试题
- [转贴]经典面试题
- IBM经典面试题
- .Net经典面试题
- C++经典面试题
- IBM经典面试题
- C++经典面试题
- [转贴]经典面试题
- 经典java面试题
- A Sweet Journey
- 【黑马程序员】【Foundation框架】常用类NSString和NSMutableString字符串
- 标签传播算法(Label Propagation)及Python实现
- R语言RMySQL包的使用注意事项
- storyboard之 Segue
- 单链表经典面试题
- 汇编浮点运算指令集
- java开发环境配置
- There is a board with
- 【版本二】手动将jar添加到maven仓库中
- python中一些比较实用的小技巧
- 【黑马程序员】【Foundation框架】字典NSDictionary和NSMutableDictionary
- BZOJ水题
- Copy List with Random Pointer