单链表是笔试以及面试手写代码中常考的数据结构之一。下面实现了单链表的常见操作:创建单链表、删除节点、打印单链表(包括正向打印以及逆向打印)、反转单链表、找出单链表的倒数第K个节点、合并两个有序单链表等操作。

代码(C++):

//笔试面试单链表常用操作编程实现
#include <iostream>
#include <stack>
#include <cstdlib>using namespace std;//单链表节点数据结构定义
typedef struct link_node_s{int m_val;struct link_node_s *next;
}link_node_t,*link_list_t;//函数:创建单链表(头插法)
link_list_t create_linklist(int *a,int n);//函数:打印单链表(从头到尾)
void print_linklist(link_list_t head);//函数:打印单链表(从尾到头)
void print_linklist_reverse(link_list_t head);//函数:新建链表节点
link_list_t creart_linknode(int val);//函数:删除链表中的某一个节点(前提条件:该节点一定存在)
//性能要求:在O(1)时间复杂度内实现
void delete_node_exist(link_list_t *head,link_list_t node_deleted);//函数:删除链表中数据值等于给定值的节点
void delete_node(link_list_t *head,int val);//函数:获得链表中的倒数第K个节点
link_list_t get_kth_node(link_list_t head,int k);//函数:反转链表
link_list_t reverse_linklist(link_list_t head);//函数:合并两个已排序的链表(递归方法实现)
link_list_t merge_linklist_recursive(link_list_t head1,link_list_t head2);int main(){const int num1 = 8;const int num2 = 10;int *a = new int[num1];int *b = new int[num2];int *a_sorted = new int[num1];int *b_sorted = new int[num2];srand(1);for(int i = 0;i < num1;++i){*(a + i) = rand() % 100;*(a_sorted + i) = 50 - i * 2 + 8;}for(int i = 0;i < num2;++i){*(b + i) = rand() % 200;*(b_sorted + i) = 50 - i * 4 + 1;}cout << "**********创建链表测试**********" << endl;link_list_t list1 = create_linklist(a,num1);link_list_t list2 = create_linklist(b,num2);link_list_t list_sorted1 = create_linklist(a_sorted,num1);link_list_t list_sorted2 = create_linklist(b_sorted,num2);cout << "**********输出链表测试(正向输出)**********" << endl;cout << "链表1:" << endl;print_linklist(list1);cout << "链表1(已序):" << endl;print_linklist(list_sorted1);cout << "链表2(已序):" << endl;print_linklist(list_sorted2);cout << "**********输出链表测试(逆向输出)**********" << endl;print_linklist_reverse(list1);cout << "**********获取链表的倒数第K个节点测试**********" << endl;int k = 3;link_list_t kth_node = get_kth_node(list1,k);if(NULL == kth_node)cout << "链表中倒数第" << k << "个节点不存在" << endl;elsecout << "链表中倒数第" << k <<"个节点是: " <<kth_node->m_val << endl; k = 8;kth_node = get_kth_node(list1,k);if(NULL == kth_node)cout << "链表中倒数第" << k << "个节点不存在" << endl;elsecout << "链表中倒数第" << k <<"个节点是: " <<kth_node->m_val << endl; k = 11;kth_node = get_kth_node(list1,k);if(NULL == kth_node)cout << "链表中倒数第" << k << "个节点不存在" << endl;elsecout << "链表中倒数第" << k <<"个节点是: " <<kth_node->m_val << endl; cout << "**********删除链表中一定存在的节点测试(输入参数是要删除的节点指针)**********" << endl;link_list_t node_deleted = list1;while(node_deleted->m_val != *(a + 4))node_deleted = node_deleted->next;cout << "删除节点" << *(a + 4) << "之后的单链表:" << endl;delete_node_exist(&list1,node_deleted);print_linklist(list1);node_deleted = list1;while(node_deleted->m_val != *(a + 6))node_deleted = node_deleted->next;cout << "删除节点" << *(a + 6) << "之后的单链表:" << endl;delete_node_exist(&list1,node_deleted);print_linklist(list1);cout << "**********删除链表中值等于给定值的节点测试(不一定存在,输入参数是int型值)**********" << endl;const int val_deleted = 22;delete_node(&list1,val_deleted);cout << "删除值等于" << val_deleted << "之后的链表:" << endl;print_linklist(list1);cout << "**********合并链表测试**********" << endl;link_list_t merge_list_head = merge_linklist_recursive(list_sorted1,list_sorted2);print_linklist(merge_list_head);cout << "**********逆转链表测试**********" << endl;link_list_t head_reverse = reverse_linklist(merge_list_head);cout << "逆转之后的链表:" << endl;cout << "头节点:" << head_reverse->m_val << endl;print_linklist(head_reverse);return 0;
}//函数:创建单链表(头插法)
link_list_t create_linklist(int *a,int n){link_list_t head = NULL;if(NULL == a || 0 == n)return NULL;for(int i = 0;i < n;++i){link_list_t new_node = creart_linknode(*(a + i));if(NULL == head){head = new_node;}else{new_node->next = head;head = new_node;}}return head;
}//函数:新建链表节点
link_list_t creart_linknode(int val){link_list_t node = new link_node_t;node->m_val = val;node->next = NULL;return node;
}//函数:打印单链表
void print_linklist(link_list_t head){link_list_t node = head;cout << "正向输出单链表" << endl;while(node != NULL){cout << node->m_val << " ";node = node->next;}cout << endl;return;
}//函数:打印单链表(从尾到头)
void print_linklist_reverse(link_list_t head){stack<int> node_stack;link_list_t node = head;while(node != NULL){node_stack.push(node->m_val);node = node->next;}cout << "逆向输出单链表" << endl;while(!node_stack.empty()){cout << node_stack.top() << " ";node_stack.pop();}cout << endl;return;
}//函数:删除链表中的某一个节点(前提条件:该节点一定存在)
//性能要求:在O(1)时间复杂度内实现
void delete_node_exist(link_list_t *head,link_list_t node_deleted){//算法思想://通过拷贝要删除节点的后继节点的内容覆盖要删除节点的内容,然后删除要删除节点的后继节点即可//要考虑的特殊情况是:要删除的节点是链表尾部节点,仍然需要遍历链表if(NULL == head || NULL == node_deleted)return;//要删除的节点不是尾节点if(node_deleted->next != NULL){link_list_t next_node = node_deleted->next;node_deleted->m_val = next_node->m_val;node_deleted->next = next_node->next;delete next_node;next_node = NULL;}//链表中只有一个节点else if(*head == node_deleted){delete node_deleted;node_deleted = NULL;*head = NULL;}//要删除的节点是尾节点else{link_list_t node = *head;while(node->next != node_deleted)node = node->next;node->next = node_deleted->next;delete node_deleted;node_deleted = NULL;}return;
}//函数:获得链表中的倒数第K个节点
link_list_t get_kth_node(link_list_t head,int k){//性能:只需遍历链表一遍即可//算法思想:设置两个指针,一个指向链表头部,一个指向第k个节点,然后两个指针同时向后移动,当第二个指针指向链表的尾节点时,第一个指针指向的节点便是倒数第K个节点//注意代码的鲁棒性,防止程序的崩溃if(NULL == head || k <= 0)return NULL;//设置两个指针link_list_t p1 = head,p2 = head;int i = 0;//第二个指针向前走k-1步while(i < k - 1 && p2->next != NULL){p2 = p2->next;++i;}//注意链表中总节点数小于K的情况if(i != k - 1 && NULL == p2->next)return NULL;//两个指针同时向后前进while(p2->next != NULL){p1 = p1->next;p2 = p2->next;}return p1;
}//函数:反转链表
//返回值:反转之后的链表头节点
link_list_t reverse_linklist(link_list_t head){//链表为空或者只有一个节点if(NULL == head || NULL == head->next)return head;link_list_t prev_node = NULL,next_node,cur_node = head,head_reverse;while(cur_node != NULL){next_node = cur_node->next;if(NULL == next_node)head_reverse = cur_node;//原链表尾节点即逆转后链表的头节点cur_node->next = prev_node;prev_node = cur_node;cur_node = next_node;}return head_reverse;
}//函数:删除链表中数据值等于给定值的节点
void delete_node(link_list_t *head,int val){if(NULL == head){cout << "Delete node failed :The node to be delete not exist!" << endl;return;}if(val == (*head)->m_val){link_list_t node = *head;*head = (*head)->next;delete node;return;}//首先判断该节点是否存在链表中link_list_t node = *head;while(node->next != NULL){if(val == node->next->m_val)break;node = node->next;}//存在满足条件的节点if(node->next != NULL){link_list_t node_delete = node->next;node->next = node_delete->next;delete node_delete;}elsecout << "删除失败:链表中不存在值等于" << val << "的节点" << endl;return;
}//函数:合并两个已排序的链表(递归方法实现)
link_list_t merge_linklist_recursive(link_list_t head1,link_list_t head2){if(NULL == head1)return head2;else if(NULL == head2)return head1;link_list_t merge_head = NULL;if(head1->m_val < head2->m_val){merge_head = head1;merge_head->next = merge_linklist_recursive(head1->next,head2);}else{merge_head = head2;merge_head->next = merge_linklist_recursive(head1,head2->next);}return merge_head;
}

测试平台:WIn8+Ubuntu12.04+Vim+G++:

运行结果:

笔试面试常考数据结构-单链表常用操作编程实现相关推荐

  1. C++我记得应该是当初笔试面试常考的

    C++我记得应该是当初笔试面试常考的.当然指针也是的 布科思直接问我STL 东莞的无人机公司笔试题里面考了些C++的,我不会 武汉的环宇智行笔试题也是一些C++的似乎是面向对象构造函数那些东西,这种我 ...

  2. 计算机网络笔试面试常考

    整理一下计算机网络部分的面试常考点, 参考书籍:<计算机网络>第五版 谢希仁的那本,希望对大家有所帮助 OSI,TCP/IP,五层协议的体系结构,以及各层协议 OSI分层 (7层):物理层 ...

  3. 数字IC笔试面试常考问题及答案

    来源:知乎 链接:https://zhuanlan.zhihu.com/p/261298869 基础知识 原理务必理解透彻. 锁存器的结构-DFF的结构-建立保持时间-亚稳态-STA-CDC. 亚稳态 ...

  4. Java面试常考之 单例设计模式(饿汉式单例、 懒汉式单例)

    所谓的单例设计指的是一个类只允许产生一个实例化对象. 对于单例设计模式也有两类形式:懒汉式.饿汉式. 饿汉式单例思想: 单例模式:表示任何类的对象有且只有一个. 首先控制对象的产生数量:将构造方法私有 ...

  5. 面试常考的常用数据结构与算法

    面试常考的常用数据结构与算法 数据结构与算法,这个部分的内容其实是十分的庞大,要想都覆盖到不太容易.在校学习阶段我们可能需要对每种结构,每种算法都学习,但是找工作笔试或者面试的时候,要在很短的时间内考 ...

  6. PHP面试常考内容之Memcache和Redis(2)

    你好,是我琉忆. 继周一(2019.2-18)发布的"PHP面试常考内容之Memcache和Redis(1)"后,这是第二篇,感谢你的支持和阅读. 本周(2019.2-18至2-2 ...

  7. PHP面试常考内容之面向对象(3)

    PHP面试专栏正式起更,每周一.三.五更新,提供最好最优质的PHP面试内容. 继上一篇"PHP面试常考内容之面向对象(2)"发表后,今天更新面向对象的最后一篇(3).需要(1),( ...

  8. java面试常考_JAVA面试常考系列十

    JAVA面试常考系列十 题目一 Servlet是什么? Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,是用Java编写的服务器端程序,主要的 ...

  9. JAVA面试常考系列十

    转载自 JAVA面试常考系列十 题目一 Servlet是什么? Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,是用Java编写的服务器端程序 ...

最新文章

  1. 非计算机专业自学1年拿到算法offer的总结(附学习路线)
  2. 树结构有什么好处_什么啊?面试官还在问HashMap了,老知识点了啊
  3. python中的对象拷贝
  4. oracle中姓名取姓氏,Oracle SQL - 解析一個名稱字符串並將其轉換爲第一個姓氏和名字...
  5. [Algorithm] Good Fibonacci
  6. [转]Oracle DB管理内存
  7. Jmeter 分布式测试完整实践过程(部署成功)
  8. kibana管理界面日志级别查询_微服务海量日志怎么处理,我不允许你还不知道这款工具...
  9. 脏数据-数据量纲差异
  10. C++ Arduino 串口输出读取整合
  11. WampServer图标黄色如何解决
  12. Office 解决WORD转PDF未显示书签。
  13. excel表格末尾添加一行_Excel2007:给excel表格添加边框线
  14. 透明网桥的自学习算法
  15. 关于瑞星杀毒软件对浏览器速度的影响
  16. 操作系统——处理系统的分类
  17. nginx 模糊匹配location写法
  18. 一文读懂图像信号中的高频和低频
  19. 关于三大主流移动操作系统的看法
  20. hashcat 使用

热门文章

  1. si_meminfo获取当前系统物理内存使用情况
  2. python中的lambda函数用法--无需定义函数名的函数或子程序,避免代码充斥着大量单行函数
  3. logistics回归分析+代码详解
  4. [C/C++]记录:使用sprintf_s时第二个参数不严格计算导致栈损坏
  5. css使图片变成黑白效果 - 代码篇
  6. PC端中文机械设备企业网页模板
  7. 小丑马戏团风格英文404网页模板
  8. 好看的个人qq主页-导航页源码
  9. Puma单栏博客Typecho主题
  10. zblog主题OL免费清爽资讯博客主题