数据结构与算法(C++)大纲
1.栈
栈的核心是LIFO(Last In First Out),即后进先出
出栈和入栈只会对栈顶进行操作,栈底永远为0
1.1概念
栈底(bottom):栈结构的首部
栈顶(top):栈结构的尾部
出栈(Pop):结点从栈顶删除
进栈(Push):结点在栈顶位置插入
取栈顶内容操作(Top):取栈顶结点数据值的操作
空栈:当栈中结点数为0时
1.2操作
如果是入栈,要将入栈元素赋值给栈数组,再将栈顶上移一位;
出栈时要先将栈顶下移一位,再将栈顶元素赋值给引用
2.队列
普通队列效率低下,出队的时候头数组要清空,后面的元素都要向前移动
环形队列判空判满不能用head = tail判断,因为队满和队空都满足这种条件
这里只讨论环形队列
队列的核心思想是FIFO(First In First Out),即先入先出
2.1概念
队首(front):队列首元素
队尾(rear):队列尾元素
出队(Dequeue):把结点从队首删除的操作
入队(Enqueue):在队尾位置插入的操作
2.2操作
入队(新增元素)必须从队尾加入,出队(删除元素)必须从队首出去
3.线性表
3.1概念:
线性表:是零个或多个数据元素的有限序列
需要注意的是:
1. 线性表中的数据元素是有顺序的
2. 线性表中数据元素的数量是有限的
3. 线性表中数据元素个数可以为零
如图按下标排序的数据元素就可以认为是一个线性表:
线性表长度:线性表中数据元素个数称为线性表的长度, 长度为零的表称为空表.
前驱:某个数据元素的前一个数据元素称为该元素的前驱, 每个元素至多有一个前驱.
后继:某个数据元素的后一个数据元素称为该元素的后继, 每个元素至多有一个后继.
线性表的两种存储结构:
根据线性表中数据元素在内存中的存储方式可以用顺序存储结构或链式存储结构实现线性表.
用顺序存储结构即使用数组来表示线性表元素之间的顺序和对应关系. 用链式存储结构即使用指针来表示线性表元素之间的顺序和对应关系, 我们称其为链表.
3.2顺序表
核心操作
3.2.1插入元素:
先判断索引是否合法
索引如果合法
先对插入元素的位置后面进行移动,并且是倒序移动,因为顺序移动顺序表前面的元素值会一直覆盖掉后面的
假如按顺序插入,如
list1->ListInsert(0, &e1);
list1->ListInsert(1,&e2);
是不会进入for循环的,只有插入同一个位置,才会向后移动元素
移动完元素后进行赋值操作
长度++
PS:这里m_pList[k+1] = m_pList[k]写成m_pList[k] = m_pList[k-1]效果是一样的,那么上面k就要等于m_iLength = m_iLength,不然顺序表尾元素会丢失掉
bool List::ListInsert(int i, int *Elem)
{
if (i< || i>m_iLength)
{
return false;
}
else
{
//先在后面进行移动
for (int k = m_iLength - ; k >= i; k--)
{
m_pList[k + ] = m_pList[k];
}
//插入元素
m_pList[i] = *Elem;
m_iLength++;
return true;
}
}
3.2.2删除元素
对索引判断是否合法
然后先将要删的元素赋值给Elem所指向空间的值,后赋值,元素已经被删掉,获取不到了
从前往后移动,从后面往前移动会造成元素值的丢失
移动完毕
长度--
bool List::ListDelete(int i, int *Elem)
{
if (i< || i>=m_iLength)
{
return false;
}
else
{
*Elem = m_pList[i];
//先在前面进行移动,从后面开始移动会造成值的替代
//k=i+1对应着k-1,若k=i,k <= m_iLength-1,m_pList[k] = m_pList[k+1];
for (int k = i+; k <= m_iLength; k++)
{
m_pList[k-] = m_pList[k];
} m_iLength--;
return true;
}
}
3.3链表
头结点:不算在数组索引中,数据域为空,指针域指向开始的结点
核心操作:
3.3.1插入元素:
判断参数i的合法性
i不能小于0,i不能大于链表长度,i等于链表长度代表可以尾元素后插入
currentNode保存头结点
声明newNode
pNode数据域赋值给newNode数据域
新结点指向原来结点的下一个结点
原来的结点指向新结点
bool List::ListInsert(int i, Node *pNode)
{
if (i< || i>m_iLength)
{
return false;
}
Node *currentNode = m_pList;
for (int k = ; k < i; k++)
{
currentNode = currentNode->next;
}
Node *newNode = new Node;
if (newNode == NULL) //判断申请的结点内存是否为空
{
return false;
}
else
{
newNode->data = pNode->data;
newNode->next = currentNode->next;
currentNode->next = newNode;
return true;
}
}
3.3.2删除元素:
判断i是否合法,索引最大是m_iLength-1,和循环条件k<i对应
currentNode保存头指针
currentNodeBefore置空
currentNodeBefore指向currentNode的下一个结点的指针域,这样currentNode就可以被删除释放了
pNode数据域接收当前结点的数据域
删除当前结点并置空
bool List::ListDelete(int i, Node *pNode)
{
if (i< || i>=m_iLength)
{
return false;
}
Node *currentNode = m_pList;
Node *currentNodeBefore = NULL;
for (int k = ; k <= i; k++)
{
currentNodeBefore = currentNode;
currentNode = currentNode->next;
}
currentNodeBefore->next = currentNode->next;
pNode->data = currentNode->data;
delete currentNode;
currentNode = NULL;
m_iLength--;
return true;
}
4.树
4.1概念
- 孩子:子结点
- 双亲:父节点
- 度:有多少个子结点
- 有序树:固定的排列的树
- 无序树:排列与顺序无关的树
- 二叉树:所有结点小于等于2的树
- 满二叉树:二叉树中,所有分支结点都同时具有左孩子和右孩子,并且所有子节点在同一层上
- 完全二叉树:只允许树的最后一层出现空结点,且最下层的叶子节点集中在树的左部
4.2树的数组存储
核心操作:
4.2.1添加结点:
direction = 0代表添加左子节点,direction = 1代表添加右子节点
左子节点 = 2*索引+1;右子节点 = 2*索引+2
下图可以验证
继续判断索引的合法性,左子节点和右子节点同样不能小于0或者大于等于数组长度
最后将*pNode赋值给子节点
bool Tree::AddNode(int nodeIndex, int direction, int *pNode)
{
if (nodeIndex< || nodeIndex >= m_iSize)
{
return false;
}
if (m_pTree[nodeIndex] == )
{
return false;
}
if (direction == )
{
//nodeIndex * 2 + 1<0可以省略
if (nodeIndex * + < || nodeIndex * + >= m_iSize)
{
return false;
}
//判断是否有左子节点
if (m_pTree[nodeIndex * + ] != )
{
return false;
}
m_pTree[nodeIndex * + ] = *pNode;
}
if (direction == )
{
//nodeIndex * 2 + 2<0可以省略
if (nodeIndex * + < || nodeIndex * + >= m_iSize)
{
return false;
}
//判断是否有左子节点
if (m_pTree[nodeIndex * + ] != )
{
return false;
}
m_pTree[nodeIndex * + ] = *pNode;
}
return true;
}
4.2.2删除结点:
判断索引和数组值的合法性
将*pNode接收删除的对应索引的数组
将该索引数组置为0,结点值等于0代表删除
返回正确结果
bool Tree::DeleteNode(int nodeIndex, int *pNode)
{
if (nodeIndex< || nodeIndex >= m_iSize)
{
return false;
}
if (m_pTree[nodeIndex] == )
{
return false;
}
*pNode = m_pTree[nodeIndex];
m_pTree[nodeIndex] = ;
return true;
}
4.3 树的链式存储
核心操作:
前序遍历:根左右
中序遍历:左根右
后序遍历:左右根
void Node::PreorderTraversal()
{
cout << this->index<<" "<<this->data << endl;
if (this->pLChild != NULL)
{
this->pLChild->PreorderTraversal();
}
if (this->pRChild != NULL)
{
this->pRChild->PreorderTraversal();
}
} void Node::InorderTraversal()
{
if (this->pLChild != NULL)
{
this->pLChild->InorderTraversal();
}
cout << this->index << " " << this->data << endl;
if (this->pRChild != NULL)
{
this->pRChild->InorderTraversal();
}
} void Node::PostorderTraversal()
{
if (this->pLChild != NULL)
{
this->pLChild->PostorderTraversal();
}
if (this->pRChild != NULL)
{
this->pRChild->PostorderTraversal();
}
cout << this->index << " " << this->data << endl;
}
5.图
5.1概念
图:简单的说,图是一个用线或边连接在一起的顶点或结点的集合,严格的说,图是有限顶点V和边E的有序对
有向边:带有方向的边
无向边:没有方向的边
权:在图的一些应用中,要为每条边赋予一个表示大小的值,这个值就称为权
连通图:设图G是无向图,当且仅当G的每一对顶点之间都有一条路径,则称G是连通图
生成树:如果图H是图G的子图,且他们的顶点集合相同,并且H是没有环路的无向连通图(即一棵树),则称H是G的一棵生成树
极大连通子图:连通图本身
极小连通子图:为其生成树
连通分量:无向图的极大连通子图
出度:从该顶点出发的边数
入度:到达该顶点的边数
深度优先搜索:树的前序遍历
广度优先搜索:按层次来遍历的树的前序遍历
如图,存在三个连通分量
子图:如果图H的顶点和边的集合是图G的子集,那么称图H是图G的子图
强连通图:图G是一个有向图,当且仅当每一对不同的顶点u,v,从u到v和v到u都有一条有向路径
5.2图的数组存储
核心操作:
5.2.1为有向图设置邻接矩阵:
判断行列的合法性
如果行小于0,行大于等于最大容量,返回错误
如果列小于0,列大于等于最大容量,返回错误
图如下:
上图的邻接矩阵如下:
以(A,B)即(0,1),0行1列,0*8+1=1。
满足row*m_iCapacity+col计算的索引
bool cMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
if(row< || row>=m_iCapacity)
{
return false;
}
if (col < || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row*m_iCapacity + col] = val;
return true;
}
6.排序算法
6.1冒泡排序
6.2插入排序
基本思想:将一组数据分为有序组和待插入组,有序组增加,待插入组减少至0为止。
有序组一般选择左边第一个元素
6.3快速排序
数据结构与算法(C++)大纲的更多相关文章
- 翻阅《数据结构与算法javascript描述》--数组篇
导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性 ...
- 数据结构与算法javascript描述
<数据结构与算法javascript描述>--数组篇 导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScri ...
- 开启基本数据结构和算法之路--初识Graphviz
在我的Linux刀耕开荒阶段,就想开始重拾C,利用C实现常用的基本数据结构和算法,而数据结构和算法的掌握的熟练程度正是程序的初学者与职业程序员的分水岭. 那么怎么开启这一段历程呢? 按照软件工程的思想 ...
- 【转】MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- [转]MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- MySQL索引背后的数据结构及算法原理【转】
本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...
- 数据结构与算法JavaScript (一) 栈
序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...
- 数据结构与算法 Big O 备忘录与现实
不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新. 算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...
- 《java数据结构和算法》读书笔记
大学时并不是读计算机专业的, 之前并没有看过数据结构和算法,这是我第一次看. 从数据结构方面来说: 数组:最简单,遍历.查找很快:但是大小固定,不利于扩展 ...
随机推荐
- 提示缺少python.h解决办法
在安装uwsgi时,提示缺少python.h In file included :: plugins/python/uwsgi_python.h::: fatal error: Python.h: N ...
- SQL命令行修改数据库
增加列: alter table tableName add columnName varchar(30) 修改列类型:alter table tableName alter column colum ...
- 高德地图之c#后台获取一个或多个起点到单个终点的直线距离
首先我们需要一个控制台添加一个新Key(可使用服务选择Web服务,测试的时候IP白名单先不填); 直线距离是通过后台get方式请求API服务地址http://restapi.amap.com/v3/d ...
- c# 变量交换
C# 变量交换 变量交换的方法: 1.借助第三个变量: class Program { static void Main(string[] args) { Exchage(,); } /// < ...
- 得到windows聚焦图片(windows 10)
有些Windows聚焦图片确实很漂亮,很希望保留下来,但是Windows聚焦图片总更好,网上有得到聚焦图片的方法,每次都手动去弄真麻烦,于是自己编了一个小程序,自动得到Windows聚焦图片,下面是运 ...
- OCP 12c最新考试原题及答案(071-3)
3.(4-10) choose the best answer:The user SCOTT who is the owner of ORDERS and ORDER_ITEMS tables iss ...
- RDLC报表的相关技巧三(数量/金额的逐页累加)
数量/金额的逐页累加,不是当页小计. 核心步骤: 1.在Group1大组中加入小组Group2,2.Group2的组尾加入一个计算框 : =RunningValue(Fields!BaseAmount ...
- CentOS6.5更改语言设置
yum grouplist |grep cn yum groupinstall “Chinese Support”——————————————yum groupinstall “Desktop”vi ...
- expect--脚本实现免交互命令
转自:http://blog.51cto.com/lizhenliang/1607723 注意:使用expect脚本时,需要把脚本添加执行权限,然后./test.sh直接执行,不能用sh或者sourc ...
- easyui里面的加载tree的两种方式
第一种: 使用EasyUI中Tree 符合EasyUI中Tree的Json格式,我们先看一下,格式是如何的 [{ "id":1, "text":"My ...