K12学习数据结构知识点.docx

上传人:b****4 文档编号:4681463 上传时间:2022-12-07 格式:DOCX 页数:11 大小:25.13KB
下载 相关 举报
K12学习数据结构知识点.docx_第1页
第1页 / 共11页
K12学习数据结构知识点.docx_第2页
第2页 / 共11页
K12学习数据结构知识点.docx_第3页
第3页 / 共11页
K12学习数据结构知识点.docx_第4页
第4页 / 共11页
K12学习数据结构知识点.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

K12学习数据结构知识点.docx

《K12学习数据结构知识点.docx》由会员分享,可在线阅读,更多相关《K12学习数据结构知识点.docx(11页珍藏版)》请在冰豆网上搜索。

K12学习数据结构知识点.docx

K12学习数据结构知识点

数据结构知识点

  第二章

  线性表的概念及其抽象数据类型的定义

  线性表的逻辑结构线性表的定义

  线性表是n个类型相同的数据元素的有限序列,对n>0,除第一个元素无直接前驱,最后一个元素无直接后继外,其余的每个数据元素只有一个直接前驱和一个直接后继。

线性表的特点:

  1)同一性:

线性表有同类元素数据组成,每一个ai必须属于同一数据类型。

  2)有穷性:

线性表有限个数据元素组成,表长就是表中数据元素的个数。

  3)有序性:

线性表中相邻数据元素之间存在着序偶关系

  ai,ai1。

  线性表的抽象数据类型定义

  抽象数据类型定义:

见课本P38~P39。

  线性表的顺序存储

  线性表的顺序存储结构顺序存储结构的定义

  线性表的顺序存储结构是指用一组地址连续的存储单元依次存储线性表中的各个元素,使得线性表中在逻辑上相邻的数据元素存储

  在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。

采用顺序存储结构的线性表通常称为顺序表。

  将线性表归纳为:

关系线性化,节点顺序存。

  假定顺序表中有n个元素,每个元素占k个单元,第一个元素的

  (a1),则可通过如下公式计算出第i个元素的地址地址为LocLoc(ai):

  Loc(ai)Loc(a1)(i1)k

  其中,Loc(a1)称为基地址。

线性存储结构的C语言定义

  #defineMAXSIZE100typedefstruct{

  ElemTypeelem[MAXSIZE];/*ElemType可为int,char等*/

  intlast;/*记录线性表中最后一个元素在数组elem[]中的位置(下标值)*/

  }Seqlist;

  上述为定义一个结构体,结构名为Seqlist。

  知识延伸线性表顺序存储结构上的基本运算线性表的基本运算

  1、查找操作2、插入操作3、删除操作4、顺序表合并算法

  线性表顺序存储结构的优缺点分析

  线性表的链式存储

  链表定义:

采用链式存储结构的线性表称为链表。

链表的分类:

  1)按实现角度看:

链表可分为动态链表和静态链表。

2)按链接方式的角度看:

链表可分为单链表、循环链表和双链表。

单链表

  单链表上的基本操作线性表的基本运算1、初始化单链表

  InitList(LinkList*L)  {  

  }

  *L=(LinkList)malloc(sizeof(Node));/*建立头结点*/(*L)->next=NULL;/*建立空的单链表L*/

  注意:

L是指向单链表的头结点的指针,用来接收主程序中带初始化单链表的头指针变量的地址,*L相当于主程序中带初始化单链表的头指针变量。

2、建立单链表

  1)头插法建表

  算法描述:

从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新节点的数据域中,然后将新节点插入到当前链表的表头节点之后,直至读入结束标志为止。

  单链表的存储结构:

  typedefstructNode/*结点类型定义,结构体名为Node*/{

  ElemTypedata;structNode*next;

  }Node,*Linklist;/*LinkList为结构指针类型*/

  LinkList与Node*同为结构指针类型,这两种类型是等价的。

通常习惯上用LinkList说明指针变量,强调他是某个单链表的头指针变量。

例如,使用定义

  LinkListL,则L为单链表的头指针,从而提高程序的可读性。

用Node*来定义指向单链表中节点的指针,例如,Node*p,则p为指向单链表中节点的指针变量。

  算法:

  typedefstructNode{

  ElemTypedata;structNode*next;}Node,*Linklist;

  voidCreatFromHead(LinkListL){

  Node*s;charc;intflag=1;while(flag){  c=getchar;if(c!

='$'){  s=(Node*)malloc(sizeof(Node));  s->data=c;  s->next=L->next;  L->next=s;}elseflag=0;}}

  2)尾插法建表

  算法描述:

头插法建立链表虽然简单,但生成的链表中结点的次序和输入的顺序相反。

若希望二者相同,可采用尾插法建表。

该方法是将新节点插到当前单链表的尾上。

为此需增加一个尾指针r,使之指向当前单链表的结尾。

算法:

  typedefstructNode{

  ElemTypedata;

  structNode*next;}Node,*Linklist;

  voidCreatFromHead(LinkListL){

  Node*s,*r;r=L;charc;intflag=1;while(flag){  c=getchar;if(c!

='$'){  s=(Node*)malloc(sizeof(Node));  s->data=c;  r->next=s;  r=s;}else  {  flag=0;  r->next=NULL;  }}}

  3、单链表查找

  1)按序号查找

  算法描述:

设带头结点的单链表的长度为n,要查找表中第i个结点,则需要从单链表的头指针L出发,从头结点(L->next)开始顺着链域扫描,用指针p指向当前扫描到的结点,初值指向头结点,用j做计数器,累计当前扫描过的结点数(初值为0),当j=i时,指针p所指的结点就是要找的第i个结点。

算法:

  typedefstructNode{

  ElemTypedata;structNode*next;}Node,*Linklist;

  Node*Get(LinkListL,inti){

  intj=0;Node*p;p=L:

  if(inext!

=NULL)&&(jnext;j++;}

  if(p->next==NULL)returnNULL;/*找不到i*/else  returni;/*找到了i*/}

  2)按值查找

  算法描述:

按值查找是指在单链表中查找是否有节点值等于e的结点,若有的话,则返回首次找到的其值等于e的结点的存储位置,否则返回NULL。

查找过程从单链表的头指针指向的头结点出发,顺着链逐个将结点的值和给定值e作比较。

  算法:

  typedefstructNode{

  ElemTypedata;structNode*next;}Node,*Linklist;

  Node*Locate(LinkListL,ElemTypekey){

  Node*p;p=L->next;

  while(p!

=NULL){if(p->data==key)  returnp;/*找到了key*/p=p->next;}

  returnNULL;/*没有找到了key*/

  }  

  4、单链表插入操作

  问题要求:

在线性表的第i(1in1)个位置之前插入一个新元素e。

算法思想:

  查找:

在单链表中找到第i-1个结点并有指针pre指示。

申请:

申请新节点s,将其数据域的值置为e;

  插入挂链:

通过修改指针域将新节点s挂入单链表L。

  算法:

  typedefstructNode{

  ElemTypedata;structNode*next;}Node,*Linklist;

  voidInslist(ElemTypee,inti,LinkListL){

  Node*pre,*s;intk;

  if(inext;k++;}if(k==i){s=(Node*)malloc(sizeof(Node));s->data=e;s->next=pre->next;pre->next=s;returnOK;}else{printf(\插入位置不合理\);returnERROR;}}

  5、单链表删除

  问题要求:

将线性表的第i(1in1)个元素e删除算法思想:

  查找:

通过计数方式找到第i-1个结点并指针pre指示;删除第i个结点并释放结点空间。

  结果:

将长度为n的线性表(a1,,ai1,ai,,an)变成长度为n-1  的线性表(a1,,ai1,ai1,,an)算法:

  typedefstructNode{

  ElemTypedata;structNode*next;}Node,*Linklist;

  voidDelList(LinkListL,inti,ElemType*e){

  Node*pre,*s;intk;

  if(inext!

=NULL&&knext;k++;}

  if(pre->next==NULL){printf(\删除位置错误\);returnERROR;}

  s=pre->next;/*使得删除得第i个位置的指针为s*/pre->next=s->next;*e=s->data;

  free(s);/*释放被删除的结点所占的内存空间*/returnOK;}

  算法应用举例

  1、求单链表的长度算法描述:

  可以采用“数”结点的方法来求出单链表的长度,用指针p依次指向各个结点,从第一个元素开始“数”,一直“数”到最后一个结点(p->next=NULL).算法:

  typedefstructNode

  {

  ElemTypedata;

  structNode*next;}Node,*LinkList;

  intListLength(LinkListL){

  Node*p;intk=0;p=L:

  while(p->next!

=NULL){p=p->next;k++;}

  returnk;}

  2、求两个集合的差

  已知:

以单链表表示集合,假设集合A用单链表LA表示,集合B用单链表LB表示,设计算法求两个集合的差,即A-B。

算法思想:

  集合运算的规则可知,集合的差A-B中包含所有属于集合A而不属于集合B的元素。

具体做法是,对于集合A中的每个元素e,在集合B的链表LB中进行查找,若存在与e相同的元素,则从LA中将其删除。

  算法:

  typedefstructNode{

  ElemTypedata;

  structNode*next;}Node,*LinkList;

  voidDifference(LinkListLA,LinkListLB){

  Node*p,*q,*pre,*r;pre=LA;p=LA->next;while(p!

=NULL){q=LB->next;while(p->data!

=q->data&&q!

=NULL)/*查找有无相同元素*/  q=q->next;if(p->data==q->data)/*有相同元素*/{  r=p;  pre->next=p->next;/*本来pre->next=p,现改为pre->next=p->next*/  p=p->next;/*下一次判断p->next*/  free(r);/*释放被删除的元素的空间*/}else{  pre=p;/*也可写为pre=pre->next*/  p=p->next;}}}

  3、有两个单链表LA和LB,其元素均为非递减有序排列,编写一个算法,将他们合并成一个单链表LC,要求LC也是非递减有序排列。

  要求:

新表LC利用现有的表LA和LB中的元素结点空间,而不要额外申请结点空间。

例如LA(2,2,3),LB(1,3,3,4),则

  LC(1,2,2,3。

3

  算法思想:

要求利用现有的表LA和LB中的结点空间来建立新表LC,可通过更改结点的next域来重建新的元素之间的线性关系。

  为包证新表仍然递增有序,可以利用尾插法建立单链表的方法,只是新表中的结点不用malloc,而只要从表LA和LB中选择合适的点插入新表LC即可。

  算法:

  typedefstructNode{

  ElemTypedata;

  structNode*next;}Node,*LinkList;

  LinkListMergeLinkList(LinkListLA,LinkListLB){

  Node*pa,*pb,*pc;LinkListLC;

  /*pa和pb分别指向两个单链表LA和LB中的将要判断的结点,pc初值为LC且pc始终指向LC的表尾*/pa=LA->next;pb=LB->next;LC=LA;

  LC->next=NULL;/*将LC初始置为空表*/pc=LC;/*pc始终指向LC的表尾*//*当两表均未处理完时,选择较小者*/while(pa!

=NULL&&pb!

=NULL){if(pa->datadata){pc->next=pa;pc=pc->next;pa=pa->next;}else{pc->next=pb;pc=pc->next;pb=pb->next;}}

  if(pa==NULL)/*表B未处理完*/pc->next=pb;

  else/*表A未处理完*/pc->next=pa;

  free(LB);/*表C是以表A为基础,所以释放表B*/returnLC;}

  循环链表

  循环链表:

循环链表是一个首尾相接的链表。

  特点:

将单链表最后一个结点的指针域NULL改为指向头结

  点或线性表中的第一个结点,就得到了单链表形式的循环链表,并称为循环单链表。

在循环单链表中,表中所有结点被链在一个环上。

  带头结点的循环链表的算法和带头结点的单链表的算法的区别仅在与算法中判别当前结点p是否为尾结点。

单链表判别条件为

  p!

NULLorpnext!

NULL,而循环单链表的判别条件为p!

Lorpnext!

L。

  例题:

有两个带头结点的循环单链表LA、LB,编写算法,将两个循环单链表合并为一个循环单链表,其头指针为LA。

  算法思想:

先找到两个链表LA、LB的表尾,并分别指针p,q指向它们,然后将第一个链表的尾与第二个链表的第一个结点链接起来,并修改第二表的表尾q,使它指向第一个表的头结点。

算法:

  typedefstructNode

  {

  ElemTypedata;

  structNode*next;}Node,*LinkList;

  LinkListmerge_1(LinkListLA,LinkListLB){

  Node*p,*q;p=LA;q=LB;

  /*寻找A的尾结点,并置为p*/while(p->next!

=LA)  p=p->next;

  /*寻找B的尾结点,并置为q*/while(q->next!

=LB)  q=q->next;

  /*修改A的尾指针,并使之为B的第一节点*/p->next=LB->next;

  /*修改B的尾指针,并使之为A的头结点*/q->next=LA;free(LB);returnLA;}

  采用上面的方法,需要遍历链表,找到表尾,其执行时间为O(n)。

若循环单链表设置为尾指针表示,在实现上述合并时,无需循环遍历找尾结点,只需直接修改尾结点的指针域,其执行时间是O

(1)。

  算法:

  typedefstructNode{

  ElemTypedata;

  structNode*next;}Node,*LinkList;

  LinkListmerge_2(LinkListRA,LinkListLB){

  Node*p;

  p=RA->next;/*记录A的头结点*/RA->next=RB->next->next;free(RB->next);RB->next=p;

  returnRB;/*返回新循环链表的尾指针*/}

  双向链表

  双向链表:

给单链表的每个结点里再增加一个指向其前驱的指针域prior。

双链表的结点的结构如下图:

  前驱指针域typedefstructDNode{

  ElemTypedata;

  structDNode*prior,*next;}DNode,*DoubleList;

  prior  data  next数据域后继指针域双链表的结构定义如下:

  设指针p指向双链表中某一点,则有下式成立:

  1、双向链表

  ppriornextpppnextprior的前插操作

  算法思想:

欲在双向链表第i个结点之前插入一个新的结点,则指针的变化情况如下图:

  算法:

  typedefstructDNode{

  ElemTypedata;

  structDNode*prior,*next;}DNode,*DoubleList;

  intDlinkIns(DoubleListL,inti,ElemTypee){

  DNode*p,*s;intk;if(inext;k++;}

  if(p==NULL){

  printf(\插入位置不合理\);returnERROR;  }

  s=(DNode*)malloc(sizeof(DNode));s->data=e;

  s->prior=p->prior;p->prior->next=s;s->next=p;p->prior=s;returnOK;

  }  

  2、双向链表的删除操作

  算法思想:

欲删除双向链表中的第i个结点,则指针的变化情况如下图所示:

  算法:

  typedefstructDNode{

  ElemTypedata;

  structDNode*prior,*next;}DNode,*DoubleList;

  intDlinkDel(DoubleListL,inti,ElemType*e)/*将删除的元素保存到*e中*/{

  DNode*p;intk;if(inext;k++;}

  if(p==NULL)

  {printf(\插入位置错误\);returnERROR;}

  *e=p->data;

  p->prior->next=p->next;p->next=p->prior;free(p);returnOK;}

  3、应用举例

  例题:

已知:

设一个循环双链表L(a,b,c,d)编写一个算法将链表转换为L(b,a,c,d)。

  算法思想:

实际上是交换表中前两个元素的次序。

算法:

  typedefstructDNode{

  ElemTypedata;

  structDNode*prior,*next;}DNode,*DoubleList;voidswep(DLinkListL){

  DNode*p,*q,*r;p=L->next;q=p->next;r=p->prior;

  p->next=q->next;q->next->prior=p;p->prior=q;q->next=p;q->prior=r;L->next=q;returnL;}

  一元多项式的表示及相加

  一元多项式的表示

  一元多项式可按升幂的形式写成:

  ene1e2Pn(x)p0p1xp2xpnx

  其中,ei为第i项的指数,pi是指数ei的项的系数,且

  1e1e2en。

  假设Qm(x)是一个一元多项式,则它可以用一个线性表Q来表示。

即:

Q(q0,q1,q2,,qm)

  若假设mn,则两个多项式相加的结果Rn(x)Pn(x)Qn(x),也可以用线性表R来表示:

  R(p0q0,p1q1,p2q2,,pmqm,pm1,,pn)

  一元多项式的存储1、一元多项式的顺序存储表示

  2、一元多项式的链式存储表示

  在链式存储中,对一元多项式只存非零项,则该多项式中每一项

  两部分组成(指数项和系数项),用单链表存储表示的结点结构如下图:

  系数coef结点结构定义如下:

  typedefstructPolynode  {

  intcoef;  intexp;

  structPolynode*next;  }Polynode,*Polylist;

  指数exp指针next

  建立多项式链表:

  算法描述:

通过键盘输入一组多项式的系数和指数,用尾插法建立一元多项式链表。

以输入系数0为结束标志,并约定建立多项式链表时,总是按指数小到大的顺序排列。

  算法:

  typedefstructPolynode

  {

  intcoef;intexp;

  Polynode*next;}Polynode,*Polylist;PolylistPolyCreate{

  Polynode*head,*rear,*s;intc,e;

  /*申请头结点*/

  head=(Polynode*)malloc(sizeof(Polynode));rear=head;/*rear始终指向最后一个结点*/scanf(\,&c,&e);while(c!

=0){/*申请一个新的结点*/s=(Polynode*)malloc(sizeof(Polynode));  s->coef=c;s->exp=e;rear->next=s;/*将链表连接起来*/rear=s;/*链表的结尾后移一位*/

  }

  scanf(\,&c,&e);}

  rear->next=NULL;/*结束链表*/returnhead;/*返回链表的头结点*/

  3、两个多项式相加

  运算规则:

指数相同项的对应系数相加,若不为0,则构成“和  

  多项式”中的一项;

  指数不相同的项均按升幂顺序复制到“和多项式”  中。

  算法思想:

设p、q分别指向单链表polya和polyb的当前项,比较p、q结点的指数项,此得到以下运算规则:

  ①若pexpqexp,则结点p所指的一项应该是“和多项式”中的一项,令指针p后移。

  ②若pexpqexp,则将两个结点的指数相加,当和不为0时,修改结点p的系数域,释放q结点;当和为0时,应该从polya中删去p结点,同时释放p和q结点。

  ③当pexpqexp,则结点q所指的一项应该是“和多项式”中的一项,将结点q插入在p之前,同时令指针q后移。

  算法:

  typedefstructPolynode{

  intcoef;intexp;

  Polynode*next;}Polynode,*Polylist;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1