340 likes | 503 Views
代码阅读与实践 Lecture 5 主讲人:胡亚斌 E-mail : yabin.hwu@gmail.com. 大规模集成电路设计应用与实践. 系列课程之. 第四次课的回顾. 源代码的基本元素 头文件搜索路径与头文件保护 作用域和生存周期 循环结构 循环次数、循环定式与不定式、循环退出 控制结构代码阅读方法. 1. 2. 3. 4. 5. 9. 6. 10. 8. 7. 课程内容. 向量. 集合. 矩阵和表. 链表. 栈. 树. 队列. 图. STL 简介. 映射. C 语言数据结构之. 向量. 向量实现与处理.
E N D
代码阅读与实践 Lecture 5 主讲人:胡亚斌 E-mail:yabin.hwu@gmail.com 大规模集成电路设计应用与实践 系列课程之
第四次课的回顾 • 源代码的基本元素 • 头文件搜索路径与头文件保护 • 作用域和生存周期 • 循环结构 • 循环次数、循环定式与不定式、循环退出 • 控制结构代码阅读方法
1 2 3 4 5 9 6 10 8 7 课程内容 向量 集合 矩阵和表 链表 栈 树 队列 图 STL 简介 映射
C语言数据结构之 向量
向量实现与处理 • C语言中通常用数组(array)实现 • 处理方式 • for 循环 • memset • memcpy • 文件读写 fwrite和fread charpbuf0[ED_PAGE_SIZE]; for(i=0;i<ED_PAGE_SIZE;i++) pbuf[i]=0; staticcharbuf[128]; memset(buf,0,sizeof(buf)); intforcemap[MAPSZ]; inttmpmap[MAPSZ]; memcpy(forcemap,tmpmap,sizeof(tmpmap)); if(fwrite(buf,sizeof(char),n,fp)!=n) message("write() failed, don't know why",0); if(fread(buf,sizeof(char),n,fp)!=n) clean_up("read() failed, don't know why",0); note:如果源和目的区域重叠,应使用memmove代替memcpy
越界访问 • Java, C#, Ada 认为数组越界访问是一种错误,会引发异常 • Perl, Tcl/Tk 会自动扩展区域 • C/C++返回未定义的值 • 应避免缓冲区溢出问题(常被蠕虫病毒利用)
越界访问: 实例 #define MAX_ADS 5 structdr{/* accumulated advertisements */ structinterface *dr_ifp; naddrdr_gate;/* gateway */ time_tdr_ts;/* when received */ time_tdr_life;/* lifetime */ n_longdr_recv_pref;/* received but biased preference */ n_longdr_pref;/* preference adjusted by metric */ }*cur_drp,drs[MAX_ADS]; voidset_supplier(void) { structinterface *ifp; structdr*drp; [...] for(drp=drs;drp<&drs[MAX_ADS];drp++){ drp->dr_recv_pref=0; drp->dr_life=0; } [...] }
C语言数据结构之 矩阵和表
表 • 一般用struct实现 • 实例: icmp数字编码转字符串 /* Most of the icmp types */ staticstructtok icmp2str[]={ {ICMP_ECHOREPLY,"echo reply"}, {ICMP_SOURCEQUENCH,"source quench"}, {ICMP_ECHO,"echo request"}, {ICMP_ROUTERSOLICIT,"router solicitation"}, {ICMP_TSTAMP,"time stamp request"}, {ICMP_TSTAMPREPLY,"time stamp reply"}, {ICMP_IREQ,"information request"}, {ICMP_IREQREPLY,"information reply"}, {ICMP_MASKREQ,"address mask request"}, {0,NULL} };
矩阵实现(1) • 通常用二维数组实现 typedefdoubleTransform3D[4][4]; IdentMat(Transform3D m) { registerinti; registerintj; for(i=3;i>=0;--i) { for(j =3;j >=0;--j) m[i][j]=0.0; m[i][i]=1.0; } }
矩阵实现(2) • 动态分配内存实现 ddFLOAT(*rknots)[MAXORD]=0; if(!(rknots=(ddFLOAT(*)[MAXORD]) xalloc(MAXORD *numKnots*sizeof(float)))) gotono_mem; […] void mi_nu_compute_nurb_basis_function(order,span,knots,kr,C ) ddUSHORTorder; intspan; ddFLOAT*knots; ddFLOATkr[][MAXORD];/* reciprocal of knots diff */
矩阵实例:每一行元素数量不等 PclFontMapRec**index; [...] index =(PclFontMapRec**)xalloc( sizeof(PclFontMapRec*)*nindex_row); [...] for(i=0;i<nindex_row;i++){ index[i]=(PclFontMapRec*)xalloc( sizeof(PclFontMapRec)*nindex_col); [...] for(j=0;j<=nindex_col;j++) index[i][j].fid =0x0; }
C语言数据结构之 栈
抽象数据类型栈的定义 • 栈(Stack)是限制在表的一端进行插入和删除运算的线性表,通常称插入、删除的这一端为栈顶(Top),另一端为栈底(Bottom)。表中没有元素时称为空栈。 • 假设栈S=(a1,a2,a3,…an),则a1称为栈底元素,an为栈顶元素。栈中元素按a1,a2,a3,…an的次序进栈,退栈的第一个元素应为栈顶元素。
顺序栈 • 由于栈是操作受限的线性表,因此线性表的存储结构对栈也适应。栈的顺序存储结构简称为顺序栈,可用数组来实现顺序栈。因为栈底位置是固定不变的,所以可以将栈底位置设置在数组的两端的任何一个端点。 • 栈顶位置是随着进栈和退栈操作而变化,故需用一个指针top来指示当前栈顶的位置,通常称top为栈顶指针。因此,顺序栈的类型定义只需将顺序表的类型定义中的长度属性改为top指针即可。
顺序栈实现 #define STACK_INIT_SIZE 100; #define STACKINCREMENT 10; typedefstruct{ SElemType*base; SElemType*top; intstacksize; }SqStack;
上溢和下溢 • 上溢:当栈满时再做进栈运算必定产生空间溢出 • 下溢:当栈空时再做退栈运算也将产生溢出。 • 溢出是一种出错状态,应该设法避免。
栈的基本操作 • 栈的初始化InitStack操作 • 进栈Push操作 • 出栈Pop操作 • 取栈顶元素GetTop操作
栈的初始化 Status InitStack(SqStack&S){ S.base=(SElemTye*)malloc( STACK_INIT_SIZE *sizeof(SElemType)); if(!S.base)exit (OVERFLOW); S.top=S.base; S.stacksize=STACK_INIT_SIZE; returnOK; }
进栈 Status Push(SqStackS,SElemType&e){ if(S.top-S.base>=S.stacksize){ S.base=(SElemType*)realloc (S.base,(S.stacksize+STACKINCREMENT)* sizeof(SElemType)); if(!S.base)exit (OVERFLOW); S.top=S.base+S.stacksize; S.stacksize+=STACKINCREMENT; } *S.top++=e; returnOK; }
出栈 Status Pop(SqStack&S,SElemType&e){ if(S.top==S.base)returnERROR; e=*--S.top; Return OK; }
取栈顶元素 Status GetTop(SqStackS,SElemType&e){ if(S.top=S.base)returnERROR; e=*(S.top-1); returnOK; }
链栈 • 栈的链式存储结构称为链栈,它是操作受限的单链表,其插入和删除操作仅限制在表头位置上进行。 • 链栈通常用不带头结点的单链表来实现。栈顶指针就是链表的头指针。
链栈的抽象数据类型 typedefstructSNode { SElemType data; structSNode*next; }SNode,*LinkStack;
入栈 voidPush_LS(LinkStack&S,SElemType e) { p=(LinkStack)malloc(sizeof(SNode)); p->data=e; p->next=S; S=p; }
出栈 Status Pop_LS(LinkStack&S,SElemType&e) { if(S==NULL)returnERROR; e=S->data; p=S; S=S->next; free(p); }
C语言数据结构之 队列
C语言数据结构之 映射
C语言数据结构之 集合
C语言数据结构之 链表
C语言数据结构之 树
C语言数据结构之 图
C++数据结构之 STL 简介