内容来自高老师的《三维CAD建模》课,本文就主要介绍半边结构和欧拉操作以及代码实现。

1. 边界表示法及其数据结构

· 拓扑结构

a.拓扑元素:面、边、点、体

b.拓扑关系:9种。V{V},V{E},V{F};  E{V},E{E},E{F};  F{V},F{E},F{F};

· 几何信息(狭义):描述物体的大小位置和尺寸等信息。点->坐标;边->方程;面->方程;

· 拓扑与集合元素对应关系

Vertex<-->Point;    Edge<-->Curve;     Face<-->Surface;

2. 翼边数据结构(Wing-Edge)

定义:一组首尾相连封闭二维区域形成一个环(Loop)

拓扑关系选择:E{V},E{E},E{F},V{E}

翼边结构表示:

通过判定Loop在边的左边还是右边,判断绕向来找到Loop上的所有边。

这种边的结构是不满足二维流形的可定向条件。在这个基础上对翼边的结构进行改进,提出了半边结构的思想,满足了可定向性。

半边结构表示:

半边结构在计算机中的数据结构表示:

虚线代表可以生成线框模型:{V},{E},E{V}

带空的环称为(rings)

核心思想:边在三维模型的表达中是一个重要元素,以边为重点来组织数据结构

3. 基于B-rep的建模操作

3.1 欧拉操作

欧拉操作旨在有效的构建B-rep中的拓扑结构(通用、有效)

欧拉公式:V+F-E=2

扩展:V+F-E=2(S-h)+r,其中S是体的个数,h是柄的个数,r是内环的个数

3.2 欧拉操作的设计思想

基于欧拉公式来保证其有效性。希望提供一组通用、完备的B-rep的拓扑生成操作。我的理解是欧拉操作给模型的拓扑生成提供了完备的理论依据。

3.3 欧拉操作的选择(6维空间的5维超平面)

v     e     f     h    r    s     Operator

1     1     0    0    0    0       mev

0     1     1    0    0    0       mef

1     0     1    0    0    1       mvfs

0    -1     0    0    1    0       kemr

0     0    -1    1    1    0       kfmrh

· mvsf(v, f): 生成含有一个点的面,并且构成一个新的体

· kvsf: 删除一个体,该体仅含有一个点的面

· mev(v1, v2, e):生成一个新的点e2,连接该点到已有点v1,构造一条新的边

· kev(e, v):删除一条边和该边的一个端点v

· mef(v1,v2,f1,f2,e):连接面f1上的两个点v1,v2,生成一条新边e,并产生一个新面

· kef(e):删除一条边e和该边的一个邻面f

· kemr(e):删除一条边e,生成该边某一邻面上的新的内环

· mekr(v1,v2,e):连接两个点v1、v2、,生成一条新的边e,并删除掉v1和v2所在面上一个内环

· kfmrh(f1,f2,):删除与面f1相接触的一个面f2,生成面f1上的一个内环,并形成体上的一个通孔

· mfkrh(f1,f2):删除面f1上的一个内环,生成一个新的面f2,由此也删除了体上的一个通孔

两个辅助操作:

· semv(e1,v,e2):将e1分割成两段,生成一个新的点v和一条新的边e2

· jekv(e1,e2):合并两条相邻的边e1、e2,删除它们的公共端点

以上欧拉操作仅适用正则形体

3.4 欧拉操作具体功能与实现

(1)mvfs():定义一个体、一个面、一个外环、一个点。

伪代码:

1 OBJECT *mvfs()
2 {
3 FACE *f; OBJECT *ob; LOOP *lp; VERTEX *v;//对以上元素开辟空间
4 ob->sfaces = f; f->fsolid = ob;
5 f->floops = lp; lp->lface = f; lp->ledge = NULL;
6 return ob;
7 }

(2)mev():构造一个新点,同是构造一条连接新点与一给定点的边

伪代码:

 1 HalfEdge *mev(v1, lp)
2 {
3 HalfEdge *he1, *he2, *he;
4 Edge *eg; VERTEX *v2;
5 he1->edge = he2->edge = eg;
6 eg->he1 = he1; eg->he2 = he2;
7 he1->wloop = he2->wloop = lp;
8 he1->startv = v1;
9 he2->startv = v2;
10 he1->next = he2;
11 if (lp->ledge == NULL)
12 he2->next = he1;
13 lp->ledge = he1;
14 else
15 for (he = lp->ledge; he = next->startv != v1; he = he->next)
16 he2->next = he->next;
17 he->next = he1;
18 return he1;
19 }

这里列出的伪代码是上课讲解的一部分,后面会附上C++的源码。

我自己的理解,关键在于弄懂欧拉操作构造实体时候它的Loop环绕向一定要正确,每个拓扑面的关系,根据这个自己可以很容易的实现上面的伪代码。

3.5 欧拉操作的几个讨论

可以证明:欧拉操作是有效的;用欧拉操作对形体操作结果在物理上是可实现的,欧拉操作是完备的,任何形体可在有限步的欧拉操作中构造出来。

· 所有流形体的B-rep,欧拉操作都能构造

 · 在拓扑结构上都有效

· 将其正确嵌入3维空间结果一定是流形体

这些都给CAD模型中流形体的构建提供了理论的依据,所以底层的大厦由此慢慢开始建立,就像数学的光辉殿堂一样,理论的强有力的证明为它带来了严谨而且让人信服的意义。

3.6 扫成操作(Sweeping)

  日常生活中的物体都是由基本的长方体、圆柱(70%)以及锥、球等形成

  扫成体:有一个平面区域(直线段、圆弧、自由曲线围成的二维曲线),延一条可定的轨迹线,扫描产生三维空间点集

  平移扫成(translational sweeping)    轨迹是一条直线。

几何构造:

· 每一个给定点->新点->新边(侧边)

· 每一个给定边->新边->新面(平面,圆柱面、指纹面,自由曲面)

伪代码:

 1 Sweep(S:Solid, F:Face, V:Vector, d:Real)
2 begin:
3 L = loop of F;
4 firstv = first Vertex of L;
5 firstup = firstv + d.v;
6 mev(firstv, firstup, newe);
7 prevup = firstup; nextv = next Vertex of L;
8 while (nextv not equal to firstv)
9 begin:
10 up = nextv + d.v;
11 mev(nextv, up, newe);
12 mef(prevup, up, F, newf, newe);
13 prevup = up; nextv = next Vertex of L;
14 end
15 mef(prevup, firstup, F, newf, newe);
16 end

3.7 相关实际实现代码分析

  作业的要求是实现实现基本的欧拉操作,完成带孔正则物体的构造。我采用的是Glut作为显示部分,自己编写半边结构和欧拉操作。总体的模块分为HalfEdgeDS负责半边结构的定义和欧拉操作实现,SolidFactoy负责产生实体Solid通过欧拉操作或Sweep扫成,GlutDisplay负责显示得到的Solid模型。

半边结构的定义:

/************************************************************************/
/* Author: Li Xin */
/* Date: 2013-10-19 */
/************************************************************************/ class Solid;
class Face;
class Loop;
class Edge;
class HalfEdge;
class Vertex;
class Point; //体
class Solid
{
public: Solid():prevs(NULL), nexts(NULL), sface(NULL), edge(NULL){} Solid *prevs;
Solid *nexts;
Face *sface; //首面;
Edge *edge; //用于线框显示的边
}; //面
class Face
{
public: Face():prevf(NULL), nextf(NULL), fsolid(NULL), floops(NULL){} Face *prevf;
Face *nextf;
Solid *fsolid;
Loop *floops; //首环
}; //环
class Loop
{
public: Loop():prevl(NULL), nextl(NULL), lface(NULL), ledge(NULL){} Loop *prevl;
Loop *nextl;
Face *lface;
HalfEdge *ledge;//首边
}; //半边
class HalfEdge
{
public: HalfEdge():prev(NULL), next(NULL), adjacent(NULL), startv(NULL), endv(NULL), hloop(NULL), edge(NULL){} HalfEdge *prev;
HalfEdge *next;
HalfEdge *adjacent;
Vertex *startv;
Vertex *endv;
Loop *hloop;
Edge *edge; //边
}; //边
class Edge
{
public: Edge():preve(NULL), nexte(NULL), HalfEdge1(NULL), HalfEdge2(NULL){} Edge *preve;
Edge *nexte;
HalfEdge *HalfEdge1;
HalfEdge *HalfEdge2;
}; //几何点
class Point
{
public: double coord[3];
double* GetCoord()
{
return coord;
}
void SetCoord(double x, double y, double z);
void SetCoord(Point point);
friend inline istream & operator >> (istream & is,Point & point)
{
is >> point.coord[0] >> point.coord[1] >> point.coord[2];
return is ;
}
friend inline ostream& operator << (ostream & os,Point & point)
{
os << "( " << point.coord[0] << ", " << point.coord[1] << ", " << point.coord[2] << " )";
return os ;
}
}; //顶点
class Vertex
{
public: Vertex():prevv(NULL), nextv(NULL) {} Vertex *prevv;
Vertex *nextv;
Point point;
}; class Half_Edge_DS
{
public: Half_Edge_DS():solid(NULL){}
~Half_Edge_DS();
//数据结构
Solid *solid; //欧拉操作
Solid * mvfs(Point point, Vertex *& newVertex); //构造一个体,一个面,一个外环,一个点
HalfEdge * mev(Vertex *v1, Point p2, Loop *lp ); //构造一个新点,同时构造一条连接新点与一给定点的边
Loop * mef(Vertex *v1, Vertex *v2, Loop *lp);//构造一个边,一个面,一个环
Loop * kemr(Vertex *v1, Vertex *v2, Loop *lp);//删除一条边构造一个环
void kfmrh(Loop *outlp, Loop *lp);//删除一个与面f1相接触的一个面f2,声称面f1上的一个面上内环,并形成体上一个通孔 };

mvfs的实现:

 1 Solid * Half_Edge_DS::mvfs(Point point, Vertex *& newVertex)
2 {
3 //建立点、面、体、环
4 Solid *newSolid = new Solid;
5 Face *newFace = new Face;
6 Loop *newLoop = new Loop;
7
8 newVertex = new Vertex;
9 //记录初始点的几何信息
10 newVertex->point.SetCoord(point);
11
12 //构建拓扑关系
13 newSolid->sface = newFace;
14 newFace->fsolid = newSolid;
15 newFace->floops = newLoop;
16 newLoop->lface = newFace;
17 newLoop->ledge = NULL;
18 return newSolid;
19 }

mev的实现:

 1 HalfEdge * Half_Edge_DS::mev( Vertex *v1, Point p2, Loop *lp )
2 {
3 Solid *solid = lp->lface->fsolid;
4 HalfEdge *he1 = new HalfEdge;
5 HalfEdge *he2 = new HalfEdge;
6 HalfEdge *he = new HalfEdge;
7 Edge *edge = new Edge;
8
9 Vertex *v2 = new Vertex;
10 v2->point.SetCoord(p2);
11
12 he1->edge = he2->edge = edge;
13 edge->HalfEdge1 = he1;
14 edge->HalfEdge2 = he2;
15
16 he1->hloop = he2->hloop = lp;
17 he1->startv = v1;
18 he1->endv = v2;
19 he2->startv = v2;
20 he2->endv = v1;
21
22 he1->adjacent = he2;
23 he2->adjacent = he1;
24
25 if (lp->ledge == NULL)
26 {//First create edge
27 he1->next = he2;
28 he2->prev = he1;
29 he2->next = he1;
30 he1->prev = he2;
31 lp->ledge = he1;
32 }
33 else
34 {//Following create edges
35 for (he = lp->ledge; he->next->startv != v1; he = he->next);
36
37 he1->next = he2;
38 he1->prev = he;
39 he2->next = he->next;
40 he2->prev = he1;
41 he->next->prev = he2;
42 he->next = he1;
43 }
44
45 //Maintain Edge List
46 Edge *curEdge = solid->edge;
47 while (curEdge != NULL && curEdge->nexte != NULL)
48 {
49 curEdge = curEdge->nexte;
50 }
51 if (curEdge == NULL) solid->edge = edge;
52 else
53 {
54 curEdge->nexte = edge;
55 edge->preve = curEdge;
56 }
57
58 return he1;
59 }

mef的实现:

 1 Loop * Half_Edge_DS::mef( Vertex *v1, Vertex *v2, Loop *lp )
2 {
3 Solid *solid = lp->lface->fsolid;
4 Face *face = new Face;
5 Loop *loop = new Loop;
6 HalfEdge *he1 = new HalfEdge;
7 HalfEdge *he2 = new HalfEdge;
8 Edge *edge = new Edge;
9
10 //Create HalfEdge and Edge
11 he1->startv = v1;
12 he1->endv = v2;
13 he2->startv = v2;
14 he2->endv = v1;
15 he1->adjacent = he2;
16 he2->adjacent = he1;
17
18 edge->HalfEdge1 = he1;
19 edge->HalfEdge2 = he2;
20 he1->edge = he2->edge = edge;
21
22 //Find the HalfEdge
23 HalfEdge *tmphe1, *tmphe2, *tmphe;
24 for (tmphe = lp->ledge; tmphe->startv != v1; tmphe = tmphe->next);
25 tmphe1 = tmphe;
26
27 for (; tmphe->startv != v2; tmphe = tmphe->next);
28 tmphe2 = tmphe;
29 tmphe = tmphe->next;
30 while (tmphe->startv != v2)
31 {
32 tmphe = tmphe->next;
33 }
34 bool HaveRoll = false;
35 if(tmphe != tmphe2)
36 {
37 HaveRoll = true;
38 tmphe2 = tmphe;
39 }
40
41 //for (tmphe2 = lp->ledge; tmphe2->endv != v2; tmphe2 = tmphe2->next);
42
43 // he1->next = tmphe2->next;
44 // he1->prev = tmphe1;
45 // he2->next = tmphe1->next;
46 // he2->prev = tmphe2;
47 // tmphe1->next->prev = he2;
48 // tmphe1->next = he1;
49 // tmphe2->next->prev = he1;
50 // tmphe2->next = he2;
51
52 he1->next = tmphe2;
53 he1->prev = tmphe1->prev;
54 he2->next = tmphe1;
55 he2->prev = tmphe2->prev;
56
57
58 tmphe1->prev->next = he1;
59 tmphe1->prev = he2;
60
61 tmphe2->prev->next = he2;
62 tmphe2->prev = he1;
63
64 //loop have problem
65 ////////////////////////////////////
66 //Inner loop
67 loop->ledge = he1;
68 //Recur loop
69 lp->ledge = he2;
70
71 //Create A new Face
72 face->floops = loop;
73 face->fsolid = solid;
74 loop->lface = face;
75 //Add Face to Solid
76 Face *tmpFace;
77 for (tmpFace = solid->sface; tmpFace->nextf != NULL; tmpFace = tmpFace->nextf);
78 tmpFace->nextf = face;
79 face->prevf = tmpFace;
80 face->fsolid = solid;
81
82
83 //Maintain Edge List
84 Edge *curEdge = solid->edge;
85 while (curEdge != NULL && curEdge->nexte != NULL)
86 {
87 curEdge = curEdge->nexte;
88 }
89 if (curEdge == NULL) solid->edge = edge;
90 else
91 {
92 curEdge->nexte = edge;
93 edge->preve = curEdge;
94 }
95
96 return loop;
97
98 }

  其实mef考虑的时候,有两种情况。1.不带内环,3次mev操作然后mef操作;2.带内环mef,在kemr之前的,这时候在寻找半边的时候需要注意一下半边的方向,这里我写的代码判断复杂了,画一个图分析下,也很好改,这里就不再赘述了。

kemr的实现:

 1 Loop * Half_Edge_DS::kemr( Vertex *v1, Vertex *v2, Loop *lp )
2 {
3 Face *face = lp->lface;
4 Solid *solid = face->fsolid;
5 Loop *loop = new Loop;
6
7 HalfEdge *he;
8 //find the half edge
9 for (he = lp->ledge; (he->startv != v2) || (he->endv != v1); he = he->next);
10
11 //get related edge
12 Edge *edge;
13 edge = he->edge;
14
15 //create loop relation
16 he->next->prev = he->adjacent->prev;
17 he->adjacent->prev->next = he->next;
18
19 he->prev->next = he->adjacent->next;
20 he->adjacent->next->prev = he->prev;
21
22 lp->ledge = he->next->prev;
23
24 loop->ledge = he->prev;
25 loop->lface = face;
26
27 //insert the inner loop
28 if (face->floops == NULL)
29 face->floops = loop;
30 else
31 {
32 Loop *tmpLoop;
33 for (tmpLoop = face->floops; tmpLoop->nextl != NULL; tmpLoop = tmpLoop->nextl);
34 tmpLoop->nextl = loop;
35 loop->prevl = tmpLoop;
36 }
37
38 //find edge will delete
39 Edge *tmpEdge = solid->edge;
40 while ( tmpEdge != edge)
41 {
42 tmpEdge = tmpEdge->nexte;
43 }
44 //delete edge
45 if (tmpEdge->nexte == NULL)
46 {
47 tmpEdge->preve->nexte = NULL;
48 }
49 else if(tmpEdge->preve == NULL)
50 {
51 solid->edge = tmpEdge->nexte;
52 tmpEdge->nexte->preve = NULL;
53 }
54 else
55 {
56 tmpEdge->preve->nexte = tmpEdge->nexte;
57 tmpEdge->nexte->preve = tmpEdge->preve;
58 }
59 delete tmpEdge;
60 return loop;
61 }

kfmrh的实现:

 1 void Half_Edge_DS::kfmrh( Loop *outlp, Loop *lp )
2 {
3
4 Face *face1 = outlp->lface;
5 Face *face2 = lp->lface; // 要删去的顶面 的环,将它降到底面当内环,删去这个面。
6 //add inner loop to face
7 if (face1->floops == NULL)
8 face1->floops = lp;
9 else
10 {
11 Loop *tmpLoop;
12 for (tmpLoop = face1->floops; tmpLoop->nextl != NULL; tmpLoop = tmpLoop->nextl);
13 tmpLoop->nextl = lp;
14 lp->prevl = tmpLoop;
15 }
16 lp->lface = face1;
17
18 //Find the face to remove
19 Solid *solid = face1->fsolid;
20 Face *tmpFace = solid->sface;
21 while ( tmpFace != face2)
22 {
23 tmpFace = tmpFace->nextf;
24 }
25 //delete Face
26 if (tmpFace->nextf == NULL)
27 {
28 tmpFace->prevf->nextf = NULL;
29 }
30 else if(tmpFace->prevf == NULL)
31 {
32 solid->sface = tmpFace->nextf;
33 tmpFace->nextf->prevf = NULL;
34 }
35 else
36 {
37 tmpFace->prevf->nextf = tmpFace->nextf;
38 tmpFace->nextf->prevf = tmpFace->prevf;
39 }
40 delete tmpFace;
41 }

扫成操作:

 1 void SolidFactory::Sweep( Face *face, double vec[3], double d )
2 {
3 Solid *solid = face->fsolid;
4 Loop *loop;
5 HalfEdge *he;
6 Vertex *firstv;
7 Vertex *upvertex;
8 Vertex *prevupvertex;
9 Vertex *nextv;
10 Point uppoint;
11 HalfEdge *uphe;
12 HalfEdge *firstuphe;
13
14 for (loop = face->floops; loop != NULL; loop = loop->nextl)
15 {
16 he = loop->ledge;
17 firstv = he->startv;
18 uppoint.SetCoord(firstv->point.coord[0] + d*vec[0],
19 firstv->point.coord[1] + d*vec[1],
20 firstv->point.coord[2] + d*vec[2]);
21 firstuphe = _HalfEdgeDS->mev(firstv, uppoint, loop);
22 prevupvertex = firstuphe->endv;
23 he = he->next;
24 nextv = he->startv;
25 while (nextv != firstv)
26 {
27 uppoint.SetCoord(nextv->point.coord[0] + d*vec[0],
28 nextv->point.coord[1] + d*vec[1],
29 nextv->point.coord[2] + d*vec[2]);
30 uphe = _HalfEdgeDS->mev(nextv, uppoint, loop);
31 upvertex = uphe->endv;
32 _HalfEdgeDS->mef(upvertex, prevupvertex, loop);
33 prevupvertex = upvertex;
34 he = he->next;
35 nextv = he->startv;
36 }
37 _HalfEdgeDS->mef(firstuphe->endv, prevupvertex, loop);
38 }
39 }

总结

  这里我认为比较复杂的操作就是mef,kemr的操作,其实只要理解了半边的结构的本质,自己画画拓扑结构图,多多注意Loop的走向,这些问题都是可以迎刃而解的。

  这里有一个求是鹰的效果图,其中的点是我用Catia在草图中画好,然后导出坐标来用,扫成实现了最后的效果图,总过有5个实体对象,求是鹰、1、8、9、7。

实体模型图:

线框模型图:

  总体来说,仅仅实现了半边结构和欧拉操作的基本功能,不存在特别难懂和实现很费力的地方,出现的小bug调试调试也可以比较轻松的解决,具体实现的过程也学习了不少别人的实现,看到也有写成交互式,通过描绘封闭二维直线区域,指定扫成方向和距离的版本,这些实现的效果都是很不错。但是,自己动手实践的过程能够发掘出很多问题,比如对于Glut的使用,欧拉操作以及模型实现过程中的调试等。中间的代码的细节讲的不是很细,源代码工程请戳这里,brp的格式文件就是solid模型文件。

  第一行记录模型vertex个数n,以及num操作个数m,然后n行都是顶点坐标,再接下来m行是相关操作。

三维CAD——基于B_rep的建模操作的更多相关文章

  1. 三维CAD塑造——基于所述基本数据结构一半欧拉操作模型

    三维CAD塑造--基于所述基本数据结构一半欧拉操作模型(elar, B_REP) (欧拉操作  三维CAD建模课程 三维CAD塑造 高曙明老师  渲染框架 brep 带洞 带柄 B_REP brep ...

  2. 基于 php-redis 的redis操作

    基于 php-redis 的redis操作 林涛 发表于:2016-5-13 12:12 分类:PHP 标签:php,php-redis,redis 203次 redis的操作很多的,下面的例子都是基 ...

  3. 一个基于PDO的数据库操作类(新) 一个PDO事务实例

    <?php /* * 作者:胡睿 * 日期:2011/03/19 * 电邮:hooray0905@foxmail.com * * 20110319 * 常用数据库操作,如:增删改查,获取单条记录 ...

  4. AngularJS基于MVC的复杂操作案例

    AngularJS基于MVC的复杂操作案例 <!DOCTYPE html> <html> <head> <meta charset="UTF-8&q ...

  5. 梦想MxWeb3D,三维CAD协同设计平台 2019.04.09更新

    SDK开发包下载地址: http://www.mxdraw.com/ndetail_10140.html 在线演示网址: http://www.mxdraw.com:3000/ 1.  增加上传dwg ...

  6. 从基于 SQL 的 CURD 操作转移到基于语义 Web 的 CURD 操作

    中文名称 CURD 含义 数据库技术中的缩写词 操作对象 一般的项目开发的各种参数 作用 用于处理数据的基本原子操作     它代表创建(Create).更新(Update).读取(Retrieve) ...

  7. CAD打印图纸要怎么操作?简单方法分享给你

    大家日常生活中多多少少的都接触到过CAD文件,CAD图是借助CAD制图软件来进行绘制完成的.唯一的困惑就是CAD图纸的格式大多数均为dwg格式的,查看起来不是那么的方便?所以很多设计师们都会选择将图纸 ...

  8. 基于gtid复制主要操作记录

    基于gtid复制主要操作记录 一.安装系统依赖包 在主从上都要安装该依赖包. yum -y install perl-DBI yum -y install perl-DBD-MySQL yum -y ...

  9. 基于iTextSharp的PDF操作(PDF打印,PDF下载)

    基于iTextSharp的PDF操作(PDF打印,PDF下载) 准备 1. iTextSharp的简介 iTextSharp是一个移植于java平台的iText项目,被封装成c#的组件来用于C#生成P ...

随机推荐

  1. 【Nginx学习笔记】-初识Nginx

    Nginx 目录 Nginx Nginx 特点 Nginx 基本功能 Nginx 使用场景 Nginx 安装/卸载 Docker 方式运行 Ubuntu上安装 卸载Nginx Nginx 命令 Ngi ...

  2. Linux服务器下安装Composer 并使用Composer安装Thinkphp5.0

    Composer官方文档:https://docs.phpcomposer.com/00-intro.htmlComposer是一个php的包管理器.要求php版本在5.3以上. 一.安装Compos ...

  3. swoole中websoket创建在线聊天室(php)

    swoole中websoket创建在线聊天室(php) swoole现仅支持Linix,macos 创建websocket服务器 首先现在服务器创建一个websocket服务器 <?php // ...

  4. Unity优化图解

    花了2天把之前学到的一些关于优化的知识全都写了下来,放到一张表里面 https://www.processon.com/mindmap/5cf64f53e4b0bc8329e8112e

  5. 剑指offer 面试题9:用两个栈实现队列

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 使用栈实现队列的下列操作:push(x) -- 将一个元素放入队列的尾部.pop() -- 从队列首部移 ...

  6. win7安装oracle11g和oracle client和pl/sql

    一.安装oracle11g 1.下载Oracle 11g R2 for Windows的版本 下载地址:hhttps://www.oracle.com/technetwork/database/ent ...

  7. 《计算机组成原理 》& 《计算机网络》& 《数据库》 Roadmap for self-taugh student

    计算机组成原理: UCB的这门课绝对是不错的资源. Great Ideas in Computer Architecture (Machine Structures) B站:https://www.b ...

  8. MySQL 使用MD5对数据进行加密

    数据库MD5加密 -- ================ 测试 MD5 加密 ============== CREATE TABLE `testmd5`( id INT(11) NOT NULL AU ...

  9. leetcode 940. 不同的子序列 II (动态规划 ,字符串, hash,好题)

    题目链接 https://leetcode-cn.com/problems/distinct-subsequences-ii/ 题意: 给定一个字符串,判断里面不相同的子串的总个数 思路: 非常巧妙的 ...

  10. 分布式 ID 生成算法 — SnowFlake

    一.概述 分布式 ID 生成算法的有很多种,Twitter 的 SnowFlake 就是其中经典的一种. SnowFlake 算法生成 ID 的结果是一个 64bit 大小的整数,它的结构如下图: 1 ...