[C++进阶] 数据结构与算法
1 出栈&入栈问题
| 一个栈的入栈序列为ABCDE,则不可能的出栈序列为?(不定项选择题) A:ECDBA B:DCEAB C:DECBA D:ABCDE E:EDCBA |
正确答案是:AB
解析如下:
首先,入栈与出栈是交错进行的,也就是A入栈后可能立马就出栈了。也可能A、B都入栈后,再让B出栈。
- 选项A:A入,B入,C入,D入,E入。想要出栈顺序为ECD,那么E要先出,也就是E必须是最后一个入栈,第一个出栈的,那么CD先后出栈的情况是不存在的。即选项A为false;
- 选项B:A入,B入,C入,D入,D出,C出,E入,E出,B出,A出,也就是说,按照DCE的顺序,最后出栈的应该是BA才对。即选项B为false;
- 选项C:A入,B入,C入,D入,D出,E入,E出,C出,B出,A出,即选项C为true;
- 选项D:A入,A出,B入,B出,C入,C出,D入,D出,E入,E出,即选项D为true;
- 选项E:A入,B入,C入,D入,E入,E出,D出,C出,B出,A出,即选项E为true。
故,选项A与B是不可能出现的。
2 计算完全二叉树的叶子数目
一个完全二叉树有770个节点,那么其叶子的个数为 :_____?
解析:对于一个完全二叉树,如果总结点数为偶数,则度为 1 的结点数为1,如果总结点数为奇数且大于 1,则度为 1 的结点数为 0;而总结点数 770 为偶数,所以度为 1 的结点数 n1 = 1;度为 0 的结点数与度为 2 的结点数:n0 = n2 + 1;所以总结点数:n0+n1+n2 = 2n0 - 1 + 1 = 770,所以n0 = 385,即叶子结点的个数。
3 怎么判断链表中是否有环?
有多种思路可以解决,这里我们只介绍快慢指针法。
首先我们要理解什么是快慢指针。快指针 fast 每次移动 2 个节点,慢指针 slow 每次移动 1 个节点,如果快指针能够追上慢指针,那就说明其中有一个环,否则不存在环。
// 快慢指针法
int testLinkRing(LinkList *head)
{
LinkList *slow = head, *fast = head;
while (slow->next && fast->next)
{
slow = slow->next;
if (NULL == (fast = fast->next->next))
return 0; //无环
if (slow == fast)
return 1; //有环
}
return 0;
}
4 返回链表倒数第N个节点

5 删除链表中的重复项
采用三个指针来进行遍历,同时删除重复的节点,因为是有序的链表,我们就可以确定,重复的元素肯定是在一块链接,所以我们就可以,用三指针,我们这里就叫 pre、cur、next 分别代表的是前中后三个指针,我们在考虑的情况中,如果头节点开始就重复,我们就处理很起来多了一种情况就需要额外处理,所以我们添加一个头节点,变成带头节点,保证了头节点开始不会重复,那么我们就可以让 pre 指向带头的节点,cur 指向 pre 的next,nex 指向 cur 的next。
接下来我们就可以看 cur 是否和 nex 相等,相等就让 next 继续向下走,不相等然后再处理删除,cur 开始到 next 中间节点都是要删除的(包含 cur 指向,不包含 next 指向)删除,就用到了 pre,删除完成让 pre 指向 cur 就可以了。
如果 cur 值与 next 值不相等,那么就可以三个指针各自往前移动一个。
ListNode* deleteDuplication(ListNode* pHead)
{
// 先判断空
if (pHead == NULL)
{
return NULL;
}
// 判断是否只有一个节点
if (pHead->next == NULL)
{
return pHead;
}
// 我们采用带头链表,自己添加一个头
ListNode* pre = new ListNode();
pre->next = pHead; // 把头节点链接在链表上
ListNode* pre_head = pre; // 用来保存头节点,用于返回删除后的链表
ListNode* cur = pHead; //中指针
ListNode* nex = pHead->next; // 后面指针
while (nex != NULL) // 结束条件
while (nex != NULL && cur->val == nex->val)
{
nex = nex->next;
}
// 如果没有重复的那么cur的next一定等于nex
if (cur->next != nex) // 如果相等说明没有相同的节点
{
while (cur != nex) // 删除动作
{
pre->next = cur->next;
delete cur;
cur = pre->next;
}
if (nex != NULL) // 这里一定要要注意,要防止走到NULL发生段错误
nex = nex->next;
}
else
{
// 处理没有重复的情况
pre = cur;
nex = nex->next;
cur = cur->next;
}
}
ListNode* head = pre_head->next; // 释放空间,防止内存泄漏
delete pre_head;
return head;
}
6 根据要求写出函数(链表相关)。
有两个双向循环链表 A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中 data 值相同的结点删除。
typedef struct node
{
int data;
struct node *prior,*next;
}LinkNode;
void deleteSame(LinkNode *pHeadA, LinkNode *pHeadB)
{
// 判断链表是否存在
if(!pHeadA || pHeadB)
{
printf("链表不存在!\n");
return;
}
// 双层遍历链表
int breakFalg = 0; // 用于跳出第一层循环
LinkNode *curA = pHeadA->next;
while(curA != pHeadA)
{
LinkNode *curB = pHeadB->next;
while(curB != pHeadB)
{
if(curB->data == curA->data)
{
// 删除A节点
if(curA->next != NULL)
curA->next->prior = curA->prior;
curA->prior->next = curA->next;
free(curA);
curA = NULL;
// 删除B节点
if(curB->next != NULL)
curB->next->prior = curB->prior;
curB->prior->next = curB->next;
free(curB);
curB = NULL;
breakFalg = 1;
break;
}
curB = curB->next;
}
if(breakFalg == 1)
break;
curA = curA->next;
}
}
7 二叉树的3种非递归遍历方法
1. 前序遍历的非递归实现
运用了一个栈结构实现。先序遍历的遍历顺序为根节点-->左孩子-->右孩子,所以往栈中放数时先放右孩子,在放左孩子(左右孩子都不为空的情况下)。根据栈的先进后出的性质,所以先打印左孩子再打印右孩子,但是有的人可能会有疑问,那根节点呢。根节点在往栈中放左右孩子的时候就已经打印完了,所以根节点肯定在左右孩子打印之前就打印完了。这样打印顺序就为:根节点-->左孩子-->右孩子。
实现代码如下:
// 前序遍历(非递归方式)
void preorder(BiTree *T)
{
// 判断二叉树是否存在
if (T == NULL)
return;
stack<BiTree *> stack; // 利用栈结构实现
stack.push(T); // 将头节点放入栈中去
while (!stack.empty())
{
T = stack.top(); // T指向弹出剩下后的最顶端结点
stack.pop();
printf("%c", T->data); // 显示结点数据,可以更改为其它对结点操作
if (T->rchild != NULL) // 如果右孩子不为空,先放右孩子.
stack.push(T->rchild);
if (T->lchild != NULL) // 如果左孩子不为空,后放左孩子,这样才能保证打印顺序为:头节点-->左孩子-->右孩子
stack.push(T->lchild);
}
}
代码执行过程如下图所示:
2. 中序遍历的非递归实现
运用了一个栈结构实现。如果当前节点不为空,就往栈中放入该节点,然后让指向该节点的指针指向该节点的左孩子。如果当前节点为空,就弹出栈顶的节点,打印。然后让指向该节点的指针指向该节点的右孩子。
实现代码如下:
// 中序遍历(非递归方式)
void inorder(BiTree *T)
{
// 判断二叉树是否存在
if (T == NULL)
return;
stack<BiTree *> stack; // 利用栈结构实现
while (!stack.empty() || T != NULL) // 这两个条件只要满足一个,就执行下面过程
{
if (T != NULL) // 如果当前节点不为空,就把当前节点放入栈中去,然后让head指向当前节点的左节点,没有打印过程
{
stack.push(T);
T = T->lchild;
}
else if (T == NULL) // 如果当前节点为空,那么就弹出栈顶的元素,打印。然后让head指向栈顶节点的右节点
{
T = stack.top();
stack.pop();
printf("%c", T->data); // 显示结点数据,可以更改为其它对结点操作
T = T->rchild;
}
}
}
代码执行过程如下图所示:
上面圈的那两个状态是一样的,所以没写的部分和上层圈的那个状态后面的状态是一样的(只不过一个是左子树,一个是右子数)
3. 后序遍历的非递归实现
运用了一个栈结构和 vector 结构实现。最先将根节点数据插入在 vector 的位置 0,然后插入左子树的节点数据在位置0(造成逆序),再插入右子树的节点数据在位置0(也是逆序)。
实现代码如下:
//后序遍历(非递归方式)
void postorder(BiTree *T)
{
// 判断二叉树是否存在
if (T == NULL)
return;
stack<BiTree *> stack;
vector<ElemType> vec;
stack.push(T);
BiTree *p = nullptr;
while (!stack.empty())
{
p = stack.top();
stack.pop();
vec.insert(vec.begin(), p->data); // 一直在位置0插入,则根节点会在vector的最末尾(相当于逆序插入)
if (p->lchild)
stack.push(p->lchild);
if (p->rchild)
stack.push(p->rchild);
}
for (int i = 0; i < vec.size(); i++)
printf("%c", vec[i]);
}
参考:
[C++进阶] 数据结构与算法的更多相关文章
- 学习JavaScript数据结构与算法---前端进阶系列
学习建议 1.视频学习---认知 建议:在中国慕课上找"数据结构"相关的视频教程.中国大学MOOC 推荐清华大学.北京大学.浙江大学的教程,可先试看,然后根据自身的情况选择视频进行 ...
- Java进阶专题(十六) 数据结构与算法的应用(上)
前言 学习算法,我们不需要死记硬背那些冗长复杂的背景知识.底层原理.指令语法--需要做的是领悟算法思想.理解算法对内存空间和性能的影响,以及开动脑筋去寻求解决问题的最佳方案.相比编程领域的其他技术 ...
- 数据结构与算法 C++ 视频教程(4 套)百度网盘
为了大二有实力参加算法比赛,大一暑假我选择了留校,提前学习了一下数据结构和算法,这是我找的一些视频资源,分享给大家! 分别是 慕课网 玩转算法与数据结构.慕课网 玩转算法面试.慕课网 玩转数据结构 从 ...
- 开启基本数据结构和算法之路--初识Graphviz
在我的Linux刀耕开荒阶段,就想开始重拾C,利用C实现常用的基本数据结构和算法,而数据结构和算法的掌握的熟练程度正是程序的初学者与职业程序员的分水岭. 那么怎么开启这一段历程呢? 按照软件工程的思想 ...
- 【转】MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- [转]MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- MySQL索引背后的数据结构及算法原理【转】
本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...
- 数据结构与算法JavaScript (一) 栈
序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...
- 数据结构与算法 Big O 备忘录与现实
不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新. 算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...
随机推荐
- .net core启用 autoMapper
启用 autoMapper autoMapper 基于约定的对象映射器 目录 安装包 添加服务 书写映射关系 安装包 需要安装两个包:AutoMapper和AutoMapper.Extensi ...
- Asp.NetCoreWebApi - RESTful Api
目录 参考文章 REST 常用http动词 WebApi 在 Asp.NetCore 中的实现 创建WebApi项目. 集成Entity Framework Core操作Mysql 安装相关的包(为X ...
- 架构师小跟班:推荐46个非常经典的Linux面试题
大家都知道,做后端开发,做着做着就变成全栈了.一般服务器维护应该是运维的事情,但很多很多公司都是后端工程师在做.所以,基本的Linux系统维护也是后端工程师的必修课.问题一: 绝对路径用什么符号表示? ...
- Ivanti的垃圾软件landesk
landesk是Ivanti公司推出的终端管理工具,这个工具垃圾就垃圾在无法卸载,进程杀不死.文件删不掉,奉劝大家千万不要安装这个软件.前些天公司的IT部门一直在催促员工安装这个软件,我一时糊涂安装了 ...
- 解决:ERROR 1067 (42000): Invalid default value for 'login_time'
如图操作数据表的时候出现上图的错误 问题的原因就是出在timestamp的默认值不正确,针对以上问题的解决方案是:修改默认值为当前值. sql语言代码: Alter table user modify ...
- SpringMVC拦截器执行流程
1:MyInterceptor1.MyInterceptor2这2个拦截器都放行 MyInterceptor1......preHandleMyInterceptor2......preHandle ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 E. XKC's basketball team
题目链接:https://nanti.jisuanke.com/t/41387 思路:我们需要从后往前维护一个递增的序列. 因为:我们要的是wi + m <= wj,j要取最大,即离i最远的那个 ...
- 搜狐视频 登录 md5 加密破解
这是一个简单的md5加密,可以学习一下js加密的破解流程,当一个入门级的教程 第一步:请求抓包 password是32位的字母和数字组合,猜测可能是md5加密,我们md5在线工具上试一下 发现我们的猜 ...
- 查看mysql连接数和状态
查看MySQL连接数 登录到MySQL命令行,使用如下命令可以查看当前处于连接未关闭状态的进程列表: show full processlist; 若不加上full选项,则最多显示100条记录. 若以 ...
- robotframework连接mysql
1.安装mysql数据库,并启动,创建数据库test及user表(可以自定义) 2.配置robotframework环境加载DatabaseLibrary 3.安装pymysql,下载地址:https ...