数据结构总结

来源:互联网 发布:淘宝卖家拒签怎么办 编辑:程序博客网 时间:2024/06/03 10:59
1.前缀转后缀
将数字直接输出
碰到字符进行比较
栈内的和刚得到的运算符比较
栈内的小,新运算符进栈case <: OPTR.push(ch); break;
栈内大的栈内运算符出栈: case >: cout << y; OPTR.pop(); break;
相等出栈:case =: OPTR.pop();


2.递归的数据结构
//Declaration
typedef struct BinTreeNode
{
DataType data;
struct BinTreeNode* lchild;
struct BinTreeNode* rchild;
}BinTreeNode, *PBinTreeNode, BinTree, *PBinTree;


//InOrder Traverse binary tree and print out all nodes
void InOrderTraverse(PBinTree BT)
{
if (T) {
InOrderTraverse(BT->lchild);
printf(BT->data);
InOrderTraverse(BT->rchild);
       }
}




3.背包问题的递归解法
/*
description:背包问题的递归解法
输入:
输出:
author: jz 
email:zjhua678@163.com
Date: 20140818
*/


#inlcue<stdio.h>


#inlcue<stdlib.h>


#inlcue<stack>
#include<queue>
#include <iostream>
using namespace  std;
int w[10]={1,2,3,4,5,6,7,8,9,10};
int knap(int t, int n)
{
if ( t==0)
return 1;
else if (t<0 || t>0 && n<1)
return 0;
else if (knap(t-w[n-1], n-1) == 1)
{
printf ("result:n=%d,w[%d]=%d\n", n, n-1, w[n-1]);
return 1;
}
else
return (knap(t, n-1));
}


void main()
{
printf("背包问题的递归解法\n");
knap(15,10);
printf("\n");
}
4.划分无冲突子集问题
核心思想:
将1加入列表同时也将1冲突的项加入整个子集冲突的项,凡是加入子集冲突项的均不会加入该子集
便划分了不同的子集。




“过筛”的方法来解决划分子集问题。从第一个元素考虑起,凡不和第一个元素发生冲突的元素都可以和它分在同一子集中,然后再“过筛”出一批互不冲突的元素为第二个子集,依次类推,直至所有元素都进入某个子集为止
5.串的模式匹配算法
(1) 普通算法:穷举式搜索,这种匹配算法对于子串当中很少有重复字符的情况下效率还是不错的
(2) 由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现的,简称KMP算法。
6.二叉树的深度(先序中序后序)、广度、层次搜索
(递归算法)
(中序遍历)
(先序遍历)
        (后序遍历)
(非递归算法)
(中序遍历)
(先序遍历)
(后序遍历)
(按层次遍历)
7.二叉树的层次遍历
算法:
创建一个队列q;
将根放入队列;
while(队列非空)
{
    从队列取出一个元素并访问;
    如果该元素有右子树就将它放入队列;
    如果该元素有左子树就将它放入队列;
}
8.二叉树的重建 已知前序 中序 求后序
例如:先序遍历为DBACEGF,中序遍历为ABCDEFG。 
递归的方法解决问题
先序串:DBACEGF,先序的第一个节点一定是根节点,这样我们就知道了根节点是D.
再看中序, 在中序串之中,根结点的前边的所有节点都是左子树中,ABCDEFG,所以D节点前面的ABC就是左子树的中序串。再看前续串 DBACEGF,由于左子树的节点是ABC,我们可以得到左子树的前续周游的串为: BAC.子树的前序串BAC,和中序串ABC ,我们就可以递归的把左子树给建立起来。 同样,可以建立起右子树。 
9.二叉链表作为存储结构时,对于某个结点只能找到其左右孩子,而不能直接得到结点在任一序列中的前驱或后继。要想得到只能通过遍历的动态过程才行。
保存遍历过程中得到的信息
线索二叉树:(1)增加两个指针,分别指示其前驱和后继结点
10.树和森林
树的存储结构:
三种常用的链表结构
(1)双亲表示法,连续的存储结构,给各个节点编号,每个点标记父节点的编号。
 (2)孩子表示法,data child1 child2 child3  将各个子节点串起来
 (3)孩子兄弟表示法,以二叉树作为存储结构,链表中的两个连分别指向该节点的第一个子节点和下一个兄弟节点。
11.图的概念
顶点的度:和该节点相关联的边的数目
顶点的出度:以该点为弧尾的数目
弧的入度:以该点为弧头的弧的数目
        回路或环:第一个顶点和最后一个顶点相同的路径
        简单回路或环: 除第一个顶点和最后一个顶点其余顶点不重复
        有根图:有向图中存在一顶点可以到图中的其他所有顶点,该点为图的根
        连通图:若图中的任意两点均是连通的
        连通分量:无向图的极大连通子图
        强连通图:有向图中任意两点均是连通图
        强连通分量:有向图的极大连通子图
        连通图的生成树:连通图的极小连通子图。含有图中的全部n个顶点,但只有构成一棵树的n-1条边
12.图的结构
    多重链表:
       邻接矩阵:图的数组表示法:用两个数组分别存放图中顶点的信息(数据元素)和图中边(或弧)的信息(数据元素之间的关系)。
       typedef struct
{
VexType vexs[MAXVEX];/* 顶点信息*/
AdjTypearcs[MAXVEX][MAXVEX];/*邻接矩阵信息*/
intarcCount,vexCount;/*图的顶点个数*/
}Graph, *PGraph;


       连接表:
       对图中的所有顶点都建立一个单链表来存储所有依附于该顶点的弧或边,就可以把图中所有已有的弧或边的信息保存下来。而对于图中所有顶点还是使用一个一维数组来存放。这种存储方法就是邻接表表示法
       邻接表的优缺点:
       优点:容易找任一结点的第一邻接点和下一个邻接点。
       存储量小。
       缺点:判定任意两个结点之间是否有边或弧不方便。


       十字链表:
       在邻接表的弧(或边)结点中增加一个指针指向弧头相同的下一条弧,再增加一个该弧依附的弧尾顶点,即可以方便地求某个顶点的入度。
       typedef struct _ArcNode
       {
       inttailVex, headVex;/* 弧的头尾顶点的位置*/
       struct _ArcNode *hLink;/* 弧头相同的弧的链域*/
       struct _ArcNode *tLink;/* 弧尾相同的弧的链域*/
       AdjType weight;
       }ArcNode;
       十字链表的优缺点:
       优点:容易求有向图的入度和出度。
       缺点:操作较复杂


       邻接多重表       
12.图的遍历和生成树
和树的遍历类似,从图中某一顶点出发访遍图中其余结点,且使每一个结点被访问且仅被访问一次。
图的遍历算法是求解图的连通性问题、拓扑问题和求关键路径等算法的基础。
图的遍历比树的遍历复杂得多,因为图中任一顶点都可能和其他顶点相邻接。所以可能在访问某个顶点后,沿着某条路径又回到该顶点上,即图中可能存在回路。为了避免一个顶点被访问多次,就需要记下每个已经访问的顶点,为此需设立一个数组来存放。
1. Depth-first traversal (深度优先搜索)
2. Breadth-first traversal (广度优先搜索)
在访问了v之后,依次访问v的各个未曾访问过的邻接点,保证被访问的顶点的邻接点要先于后被访问的顶点邻接点被访问。(队列)
13. 最小代价生成树
prim算法:不断生长
从一个点开始,找与该点相邻的最小的边,将新点加入“点集合”,找新“点集合”相邻的最小的边。直到最后。
算法和顶点数有关和边数无关,适合求边稠密的图。


hruskal算法:不断合并
在不同的连通分量上,在E中选择代价最小的边,加入T中
14.关节点;如果删除某个图中的某个顶点V以及和V关联的各边之后,将图的一个连通分量变为两个或两个以上的连通分量时,该节点称为关节点。
连通度:删除k个节点才破坏图的连通性,称连通度为K。
深度优先生成树得到两类节点的特性:
(1)生成树有两棵或两棵以上的子树,此根节点必为关节点。
(2)生成树中某个非叶子节点V,其某棵子树的根回子树中其他节点均没有指向节点的回边。
因为一旦删除v该子树的所有节点就和整棵树失去了联系。


14.最短路径
        A到B边数最少的路径:从A出发作广度优先搜索,一旦遇到B就停止,广度优先生成树中,从A到B便是中转次数最少的路径。
    Dikstra算法:按照路径长度递增的顺序产生最短路径的的算法。(贪心算法)
        引入辅助向量D,它的每个分量D[i]表示当前所找到的从v0到vj的最短路径长度。


        具体实现如下:设置一个数组dist[n] 用于存放顶点v0到其它各顶点的最短路径及其最短路径长度其存储结构为:
        typedef struct
{
VexType vertex;/* 顶点信息*/
AdjType length;/* 最短路径长度*/
int prevex;/* 从v0到达vi(i=1,2,…n-1)的最短路径上vi的前趋顶点*/
}Path;
    Floyd算法:
    假设求从顶点vi到vj的最短路径。如果从vi到vj有弧,则从vi到vj存在一条长度为arcs[i][j]的路径,但该路径不一定是最短路径。
    首先考虑路径(vi,v0,vj)是否存在(即判别弧(vi,v0)和(v0,vj)是否存在)。如果存在,再比较(vi,vj)和(vi,v0,vj)的长度,并取其较短者作为从vi到vj的中间顶点的序号不大于0的最短路径。假如在路径上再增加一个顶点v1,也就是说,如果(vi,…,v1)和(v1,…,vj)分别是当前找到的中间顶点序号不大于0的最短路径,那么(vi,…,v1,…,vj)就有可能是从顶点vi到vj的中间顶点序号不大于1的最短路径。将它从已经得到的从vi到vj中间得到序号不大于0的最短路径比较,从中选出长度最小的路径然后再增加一个得到v2,继续试探。
15. 一个无环的有向图称作为“有项无环图”:是描述含有公共子式的表达的有效工具。
    二叉树表示子式,相同的表达式重复出现,利用有向无环图可以实现子式的共享,节约存储空间。
16.检验有向图的环
   




17.拓扑排序和关键路径
   拓扑排序步骤:
   (1)选取一个没有前驱的顶点输出。
   (2)从图中删除所有以他为尾的弧
   
   (3)重复(1)(2)直到所有顶点输出为止
   关键路径:
   由于有些路径可以并行的进行,完成工作的最短时间即开始点到完成点的最长路径。路径最长的路径叫关键路径。
18.查找、平均查找长度
顺序
二分查找
索引
静态最忧查找树:概率*层数最小


    次优查找树:二叉树的带权路径长度值在所有具有同样权值的二叉树中最小


    在有序序列的查找中,如果各个元素的查找概率都是一样的,那么二分查找是最快的查找算法,但是如果查找元素的查找概率是不一样的,那么用二分查找就不一定是最快的查找方法了,可以通过计算ASL来得知。
    
    分块查找(索引数据查找),是顺序查找的改进方法,除顺序表外还有个index table索引表
    有序的表中,索引表标记一块的最大值,加快查找顺序。
    
    二叉排序树:是一棵空树或者具有以下的性质的二叉树
               (1)左子树不空,则左子树上的所有节点的值均小于它的根节点。
               (2)若它的右子树不空,则右子树上的所有节点的值均大于它的根节点。
               (3)它的左右子树也分别为二叉排序树
               每次插入的节点均是书中的一个叶子节点,插入时不必移动其他节点,仅需改动某个节点的指针。二叉排序树是动态查找表中的一种有效方法。
               删除二叉树节点比插入要复杂些。
               若只有左子树或只有右子树:只要令Pl或Pr为双亲节点的左子树即可。
               若只有左子树或只有右子树:只要令Pl或Pr为双亲节点的左子树即可。
               若p的左右节点均不空。
二叉平衡树 AVL


B树:主要用于高维检索和文件的索引
B树的定义:一棵m阶的B树或为空树或满足下列特征的m叉树:
A.树中的每个节点至多有m棵子树
B.若根节点不是叶子节点,则至少有两棵子树
C.除根节点为的所有非终端节点至少有 m/2 棵子树
D.所有非终端节点中包含下列信息数据
E.所有的叶子节点都出现在同一层上,且不带信息。实际上这些节点的的指针为空。


B树上查找包含两种基本操作:
(1)在B树上找节点
(2)在节点中找关键字


B+树:
是应文件系统的需要而提出的一种B树的变形树。一棵m阶的B+树和B树的差异在于:
A. 有n棵子树的结点中含有n个关键字;
B. 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点的本身依关键字的大小从小到大顺序链接。
C. 所有的非终端结点可以看成是索引部分,结点中仅含有其子树(根结点)中最大(或最小)关键字。
通常在B+树上有两个头指针,一个指向根结点,另一个指向关键字最小的叶子结点。如下图所示:
B+树的插入仅在叶结点上进行。每插入一个关键码
指针索引项后都要判断结点中的子树棵数是否超出范围。
B+树的删除仅在叶结点上进行。


哈希查找表
什么是“好”的哈希函数?若对应关键字集合中的任一个关键字,经哈希函数映象到任何一个地址的概率是相等的,则称此类哈希函数是均匀(Uniform)的哈希函数。
换句话说,就是使关键字经过哈希函数得到一个“随机的地址”,以便使一组关键字的哈希地址均匀地分布在逐个地址区间,从而减少冲突。
常用的构造方法有:
(1) 直接地址法
取关键字或关键字的某个线性函数值为哈希地址。如年龄。
(2) 数字分析法
假设关键字是以r为基的数,并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址
(3) 平方取中法
取关键字平方后的中间几位为哈希地址。
(4) 折叠法
将关键字分割成位数相同的几部分,然后取这几部分的叠加和(舍去进位)作为哈希地址。
(5) 除留余数法
取关键字被某个不大于哈希表长度m的数p除后所得余数为哈希地址。
数p的选取:一般可选它为质数或不包含小于20的质因素的和数。
(6) 随机数法
通常当关键字的长度不等时采用此法比较恰当。
哈希函数


冲突及解决:
(1) 开放定址法
Hi= (H(key) + di) MOD m, i = 1, 2, …, k ( k <=m-1)
其中:m为表长,di为增量序列,可有三种取法:
A. di= 1, 2, 3, …, m-1, 称线性探测再散列;
B. di= 12, -12, 22, -22, …, k2, -k2(k <=m/2), 称为二次探测再散列;
C. di= 伪随机数序列,称伪随机探测再散列;
线性探测再散列容易出现二次聚集的情况,即在处理同义词的过程中又添加了非同义词的冲突。好处是可以保证总能找到一个不发生冲突的地址Hk,而二次探测再散列只有在m为形如4*j+3的素数时才可能。


红黑树:
红黑树的性质:
红黑树本质是二叉查找树的一种,它的性能高于普通的二叉查找树,即使是在最坏的情况下也能保证时间复杂度为O(lgn)。红黑树在每个结点上增加一个存储位表示结点的颜色(或红或黑)。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树可以保证没有一条路径会比其他路径长出两倍,因而是接近平衡的。


   红黑树的每个结点至少包含五个域:color,key,left,right 和 parent,如果某结点没有子结点或者父结点,则该结点相应的指针(p)域包含值NIL,我们将这些 NIL 当作叶子结点.(图a)。
   在实际处理过程中,往往将最底层的孩子结点和根结点的父亲都指向同一个 NIL 结点,以便于处理红黑树代码中的边界条件(这里的哨兵NIL是一个与树内普通结点有相同域的对象,它的color域为BLACK,而它的其他域——parent, left, right, key,可以设置为任意允许的值),而将其它结点当作内结点。 (图b)

  通常表示红黑树的方法是图(c),即忽略叶子与根部的父结点。(图c),图中,黑结点用黑色表示,红结点用浅阴影表示。


什么是堆

堆是一种特殊的二叉完全树。堆的一个主要特点是它以一定的偏序(a partial order)来保存所有节点[译者注:此处的偏序是指不完全的排序,堆只需要满足父节点大于两个子节点,而子节点之间没有要求]。作为一颗完全树,一层中的节点是从左到右填满的。如果一个节点没有左儿子,那么它一定没有右儿子。并且在第h层中如果存在节点,那么第h-1层必须是填满的。



0 0
原创粉丝点击