数据结构的复习.docx

上传人:b****6 文档编号:8457318 上传时间:2023-01-31 格式:DOCX 页数:14 大小:21.83KB
下载 相关 举报
数据结构的复习.docx_第1页
第1页 / 共14页
数据结构的复习.docx_第2页
第2页 / 共14页
数据结构的复习.docx_第3页
第3页 / 共14页
数据结构的复习.docx_第4页
第4页 / 共14页
数据结构的复习.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

数据结构的复习.docx

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

数据结构的复习.docx

数据结构的复习

数据结构的复习

数据:

对信息的一种符号表示。

在计算机科学中,指所有能输入到计算机中并能被计算机程序处理的符号的总称。

数据元素:

数据这个集合中的一个个体。

数据项:

数据的不可分割的最小单位。

一个数据元素可以有若干个数据项组成。

数据对象:

性质相同的数据元素的集合。

数据结构定义:

相互之间存在一种或多种关系的数据元素的集合。

⏹数据元素之间的关系——结构

⏹四种基本结构(如下图所示)

1集合

2线性结构

3树形结构

4图状结构/网状结构

数据结构的分类:

⏹逻辑结构:

数据元素之间的逻辑关系;

⏹物理结构:

数据元素在计算机中的存储方法(表现和实现)。

数据结构分类举例

⏹按逻辑结构的不同分为:

集合、线性结构、树状结构、网状结构

⏹按物理结构的不同分为:

⏹顺序结构

⏹链式结构

数据类型的定义:

一个值的集合和定义在这个值集上的一组操作的总称。

⏹ADT:

一个数学模型以及定义在该模型上的一组操作,即:

数据结构+定义在此结构上的一组操作。

⏹ADT的三元组表示(D,S,P)

⏹D:

数据;

⏹S:

D上的关系

⏹P:

D上基本操作

⏹ADT的格式定义:

ADT抽象数据类型名

{

数据对象:

数据对象的定义

数据关系:

数据关系的定义

数据操作:

基本操作的定义

}ADT抽象数据类型名

随着问题规模n的增长,算法执行时间的度量和f(n)的增长率相同,记作:

T(n)=O(f(n))

补:

若limT(n)/f(n)=c,则T(n)和f(n)是同阶无穷小,表示为T(n)=O(f(n));

其中:

n:

算法的计算量或称规模;f(n):

运算时间随n增大时的增长率;O(f(n)算法时间特征的度量。

线性表:

n个数据元素的有限序列。

⏹线性表中数据元素的个数n(n≥0)称为线性表的长度。

⏹当n=0时,称为空表。

⏹非空表的特性:

(1)有且仅有一个表头结点a1,它没有前驱,而仅有一个后继a2;

(2)有且仅有一个表尾结点an,它没有后继,而仅有一个前驱an-1;

(3)其余的结点ai(2≤i≤n1)都有且仅有一个前驱ai-1和一个后继ai+1。

这是定义线性表的结构体:

#defineLIST_INIT_SIZE100//初始分配空间

#defineLISTINCREMENT10//空间分配增量

typedefstruct{

ElemType*elem;//顺序表数组的基址

intlength;//当前长度

intlistsize;//当前分配的存储容量

}SqList

线性表的初始化:

StatusInitlist_sq(sqlist&L)

{

L.elem=(ElemType*)malloc(LIST_INIT_SIZE*

sizeof(ElemType));

if(!

L.elem)exit(OVERFLOW);

L.length=0;

L.listsize=LIST_INIT_SIZE;

ReturnOK;

}

线性表的插入:

StatusListInsert_sq(sqlist&L,inti,ElemTypee)

{

if(i<1||i>L.length+1)returnERROR;

if(L.length>=L.listsize)exit(OVERFLOW);

for(j=L.length-1;j>=i-1;--j)

L.elem[j+1]=L.elem[j];

L.elem[i-1]=e;

++L.length;

returnOK;

}//ListInsert_sq最坏情况,其时间复杂度为O(n);

线性表的删除操作:

Statuslistdelete_sq(Sqlist&L,inti,Elemtype&e)

{if(i<1||i>L.length)returnERROR;

e=L.elem[i-1];

for(j=i;j<=L.length-1;++j)

L.elem[j-1]=L.elem[j];

--L.length;returnOK;}时间复杂度为O(n);

判断线性表L是否为空

statusListEmpty_sq(sqListL)

{

If(L.length==0)

returnTRUE;

else

returnFALSE;

}

返回线性表L的长度

statusListLength_sq(sqListL)

{

returnL.length;

}

取线性表的第i个元素算法

StatusGetElem_sq(SqListL,inti,ElemType&e)

{

if(i<1||i>L.length)returnERROR;

e=L.elem[i-1];

returnOK;

}

两个线性表的合并:

Voidmergelist_sq(sqlistLa,sqlistLb,sqlist&Lc)

{pa=La.elem;pb=Lb.elem;

Lc.listsize=Lc.length=La.length+Lb.length;

pc=Lc.elem=(Elemtype*)malloc(Lc.listsize*sizeof(elemtype));

if(!

Lc.elem)exit(OVERFLOW);

pa_last=La.elem+La.length-1;

pb_last=Lb.elem+Lb.length-1;

While(pa<=pa_last&&pb<=pb_last)

{if(*pa<=*pb)*pc++=*pa++;

else*pc++=*pb++;}

while(pa<=pa_last)*pc++=*pa++;

while(pb<=pb_last)*pc++=*pb++;

}

⏹线性链表:

用一组任意的存储单元(可以不连续)存储线性表的数据元素。

注:

不连续---可零散地分布在内存中的任何位置上。

⏹线性链表的特点:

1链表中数据元素的逻辑次序和物理次序不一定相同。

即:

逻辑上相邻未必在物理上相邻。

2数据元素在存储器中的存储位置是随意的。

数据域——存储数据元素的信息。

指针域——存储直接后继的存储地址

单链表:

每个结点只有一个指针域。

带头结点的单链表:

⏹在线性链表的第一个元素结点之前附设一个结点,称为头结点。

⏹头结点的数据域不存储任何信息,其指针域存储第一个元素结点的存储位置。

⏹头指针L指向该头结点。

开始结点---用头指针指向之。

最后一个结点(尾结点)---指针域为空(无后继),用^或NULL表示。

表中其它结点---由其前趋的指针域指向之。

⏹线性链表(单链表)的定义描述:

typedefstructLNode{

ElemTypedata;

structLNode*next;

}LNode,*Linklist;

线性链表的初始化——建一个空链表

statusInitlist_L(Linklist&L){

//建立头结点,其next为空

L=(Lnode*)malloc(sizeof(Lnode));

L->next=null;

returnOK;

}

单链表的查找操作:

StatusGetelem_L(LinklistL,inti,ElemType&e)

{p=L->next;j=1;

while(p&&j

p=p->next;++j;

}

if(!

p‖j>i)returnerror;//找不到,返回ERROR

e=p->data;

returnOK;//找到第i个结点,返回OK

}

单链表的插入操作:

Statuslistinsert_L(Linklist&L,inti,elemtypee)

{p=L;j=0;

while(p&&jnext;++j;}

if(!

p‖j>i-1)returnerror;

s=(Lnode*)malloc(sizeof(Lnode));

s->data=e;

s->next=p->next;

p->next=s;

returnOK;}

单链表的删除操作:

Statuslistdelete_L(Linklist&L,inti,ElemType&e)

{p=L;j=0;

while(p->next&&jnext;++j;}

if(!

(p->next)‖j>i-1)returnERROR;

q=p->next;

p->next=q->next;

e=q->data;

free(q);

returnOK;

}

(1)在初值设置上,删除算法从头结点开始,删除范围为[1,表长],指针范围为[0,n-1];

注:

查找算法查找范围[1,表长],指针范围为[1,n];

插入算法插入范围[1,表长+1],指针范围为[0,n];

(2)在循环定位上,删除算法定位在i-1;

(3)在核心条件上,切记“删除算法”的书写。

建立一个带有n个元素的单链表

算法实现:

statusInitlist_L(Linklist&L,intn){

L=(Lnode*)malloc(sizeof(Lnode));

L->next=null;

for(i=n;i>0;--i){

p=(Lnode*)malloc(sizeof(Lnode));

scanf(&p->data);

p->next=L->next;

L->next=p;

returnOK;}

}

算法的时间复杂度:

for语句循环n次,为T(n)=O(n)

单链表的合并算法实现:

voidMergeList_L(LinkList&La,LinkList&Lb,LinkList&Lc){

pa=La->next;pb=Lb->next;

Lc=pc=La;//用La的头结点作为Lc的头结点

while(pa&&pb){

if(pa->data<=pb->data){

pc->next=pa;pc=pa;pa=pa->next;}

else{

pc->next=pb;pc=pb;pb=pb->next;}

}

if(pa)pc->next=pa;

elsepc->next=pb;

free(Lb);

}

循环链表:

线性表的另一种形式的链式存储结构。

令表中最后一个结点的指针域指向头结点,整个链表形成一个环。

双向链表:

每一个结点有两个指针域——一个指向直接后继,一个指向直接前驱

栈:

栈——限制仅在表尾进行插入或删除操作的线性表。

栈顶(top,表尾)——允许插入和删除的一端。

栈底(bottom,表头)——不允许插入和删除的一端。

空栈——表中没有数据元素。

⏹栈的特点:

后进先出(LIFO)或先进后出(FILO)

顺序栈的结构体定义:

定义:

采用C语言中分配的一维数组表示顺序表。

#definestack_init_size100//初始分配量

#definestackincrement10//分配增量

Typedefstruct{

selemtype*base;//存储空间基址

selemtype*top;//栈顶指针

intstacksize;//当前已分配的存储空间(元

素为单位)

}sqstack;

初始化一个栈——创建栈

StatusInitstack(sqstack&S){

s.base=(SElemtype*)

malloc(STACK_INIT_SIZE*sizeof(SElemtype));

if(!

s.base)exit(OVERFLOW);

s.top=s.base;

s.stacksize=STACK_INIT_SIZE;

ReturnOK;

}//initstack

进栈(插入新元素)

算法思想:

若栈满,返回OVERFLOW;否则将新元素e入栈,并返回OK。

Statuspush(sqstack&s,selemtypee){

if(s.top-s.base>=s.stacksize)

exit(OVERFLOW);

*S.top++=e;

returnOK;

}//push

出栈(删除栈顶元素)

算法思想:

若栈空,返回ERROR;否则将删除S的栈顶元素,并用e返回其值。

statuspop(sqstack&s,selemtype&e){

if(s.top==s.base)returnERROR;

e=*--s.top;

returnOK;

}//pop

取栈顶元素

算法思想:

若栈空,返回ERROR;否则将用e返回栈顶元素。

statusgettop(sqstacks,selemtype&e){

if(s.top==s.base)returnERROR;

e=*(s.top-1);

returnOK;

}//getpop

队列:

一个只能在队首进行删除、队尾进行插入的线性表。

队尾(rear):

允许插入的一端。

队头(front):

允许删除的一端。

特征:

先进先出(FIFO)。

 

树:

•结点(node)一个数据元素及若干指向其子树的分支;

•结点的度(degree)结点的子树个数;

•树的度(degree)树内各结点度的最大值;

•分支(branch)结点度不为0的结点;

•叶(leaf)结点度为0的结点;

•孩子(child)结点某结点的子树;

双亲(parent)结点相应的,该结点称为孩子的双亲

•兄弟(sibling)结点具有同一双亲的所有结点;

•祖先(ancestor)结点从根到该结点所经分支上的所有结点;

•子孙(descendant)结点以某结点为根的子树中的任一结点。

•结点的层次(level)根结点的层数为1,其余结点的层数为双亲结点的层数加1;

•树的深度(depth)树中结点的最大层数;

•有序树子树的次序不能互换;

•无序树子树的次序可以互换;

•森林m(m≥0)棵互不相交的树的集合,对于树中每个结点而言,其子树的集合即为森林。

二叉树是结点数为0或每个结点最多只有左右两棵子树的树。

二叉树是一种特殊的树,它的特点有:

(1)每个结点最多只有两棵子树,即不存在结点的度大于2的结点;

(2)子树有左右之分,不能颠倒。

二叉树的性质

性质1二叉树的第i层最多有2i-1个结点。

(i1)

性质2深度为k的二叉树最多有2k-1个结点。

(k1)

性质3对任何一棵二叉树,如果其叶结点个数为n0,度为2的非叶结点个数为n2,则有n0=n2+1。

满二叉树(FullBinaryTree)

一棵深度为k,且有2k-1个结点的二叉树。

满二叉树的特点:

每一层都取最大结点数;结点层序编号方法:

从根结点起从上到下逐层,层内从左到右,对二叉树的结点进行连续编号。

⏹完全二叉树(CompleteBinaryTree)

深度为k,有n个结点的二叉树是一棵完全二叉树,当且仅当其每个结点都与深度为k的满二叉树中层次编号1—n相对应。

完全二叉树的特点

(1)除最后一层外,每一层都取最大结点数,最后一层结点都有集中在该层最左边的若干位置。

(2)叶子结点只可能在层次最大的两层出现。

(3)对任一结点,若其右分支下的子孙的最大层次为L,则其左分支下的子孙的最大层次为L或L+1。

性质4具有n个结点的完全二叉树的深度

为+1。

性质5如果将一棵有n个结点的完全二叉树自顶向下,同一层自左向右连续给结点编号1,2,…,

n-1,n,则对任一结点i(1≤i≤n)有:

(1)若i=1,则结点i是二叉树的根,无双亲;

若i>1,则i的双亲为i/2

(2)如果2i>n,则结点无左孩子,否则其左孩子

lchild(i)是结点2i

(3)如果2i+1>n,则结点无右孩子,否则其右孩

子rchild(i)是结点2i+1

二叉树的存储结构

一、顺序存储结构

二、链式存储结构

设计不同的结点结构,可以构成不同的链式存储结构,常用的有:

二叉链表、三叉链表和线索链表

遍历二叉树(traversingbinarytree)

按某条搜索路径访问树中每一个结点,使得每个结点均被访问一次,且仅被访问一次。

先序(根)遍历:

DLR

中序(根)遍历:

LDR

后序(根)遍历:

LRD

二叉树的遍历算法主要有两种:

递归算法;非递归算法。

先序遍历算法:

StatusPreOrderTraverse(BitreeT){

if(T){

visit(T->data);

PreOrderTraverse(T->lchild);

PreOrderTraverse(T->rchild);

returnok;}

else

returnerror;

}

中序遍历算法:

voidInOrderTraverse(BiTreeT){

if(T){

InOrderTraverse(T->lchild);

Visit(T->data);

InOrderTraverse(T->rchild);

returnok;}

else

returnerror;

}

后序遍历算法:

StatusPostOrderTraverse(BitreeT){

if(T){

PostOrderTraverse(T->lchild);

PostOrderTraverse(T->rchild);

visit(T->data);

returnok;}

else

returnerror;

}

先序遍历——非递归算法:

StatusPreOrderTraverse(BitreeT,status(*visit)(TelemTypee)){

Initstack(s);p=T;

while(p||!

StackEmpty(s)){

if(p){visit(p->data);

push(s,p);p=p->lchild;}

else{

pop(s,p);p=p->rchild;}

}

returnok;

}

中序遍历——非递归算法:

StatusInOrderTraverse(BitreeT,status(*visit)(TelemTypee)){

Initstack(s);p=T;

while(p||!

StackEmpty(s)){

if(p){push(s,p);p=p->lchild;}

else{

pop(s,p);visit(p->data);

p=p->rchild;}

}

returnok;

}

线索二叉树

☐可利用二叉链表结点结构中的空指针域(共(n+1)个),在空指针域中存放结点在某种遍历次序下的前趋和后继结点信息,这种附加的指针称为“线索”。

☐为避免混淆,需改变结点结构,即增加两个标志域。

☐若结点有左子树,则标志位ltag=0,表示左链域指针lchild指向其左孩子结点;否则,令其左链域指示其前驱,ltag=1。

☐若结点有右子树,则标志位rtag=0,表示右链域指针rchild指向其右孩子结点;否则,令其右链域指示其后继,rtag=1。

☐指向结点前驱或后继的指针叫做线索。

☐加上线索的二叉树叫线索二叉树。

☐对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化。

☐按先序遍历得到的线索二叉树称为先序线索二叉树;

☐按中序遍历得到的线索二叉树称为中序线索二叉树;

☐按后序遍历得到的线索二叉树称为后序线索二叉树。

树的存储表示

1.双亲表示法

用一组地址连续的存储单元来存放树的结点,每一个结点有两个域:

Data域——存放结点的信息;

Parent域——存放该结点的双亲结点的位置;

.孩子表示法:

◆每个结点的孩子用单链表存储,称为孩子链表;

◆N个结点可以有n个孩子链表;

◆N个孩子链表的头指针可以组成一个顺序表。

4.孩子-兄弟表示法:

用二叉链表作为树的存储结构,转换规则:

每个结点的左链域指向该结点的第一个孩子,

每个结点的右链域指向下一个兄弟结点。

•简单来说,哈希表就是基于哈希函数建立的一张查找表。

•哈希函数是一个映射,其设定可以很灵活,只要使得任何关键字的哈希函数值都落在表长允许范围内即可。

对不同关键字可能得到同一哈希地址,这一现象称为“冲突”,即key1≠key2,而f(key1)=f(key2)。

并且,改进哈希函数只能减少冲突,而不能避免冲突。

•因此,在设计哈希函数时:

一方面,要考虑选择一个“好”的哈希函数;另一方面,要选择一种处理冲突的方法。

查找的分类:

静态查找:

不涉及插入和删除操作的查找。

动态查找:

涉及插入和删除操作的查找。

 

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

当前位置:首页 > PPT模板 > 国外设计风格

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

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