数据结构期末复习题纲整理人:王米孙文考试题型:选择、填空、判断、解答、算法理解题、算法设计题温馨提示:数据结构除标记要背的内容外理解的较多,请同学们认真复习,但靠死记硬背是不行的,重点在理解。
第一章:1、掌握基本概念:数据、数据元素、数据对象、数据结构、数据类型、抽象数据类型2、能够计算算法的时间复杂度数据:对信息的一种符号表示。
数据元素:数据这个集合中的一个个体。
如:学生个体。
数据对象:性质相同的数据元素的集合。
数据结构:相互之间存在一种或多种关系的数据元素的集合。
数据类型:一个值的集合和定义在这个值集上的一组操作的总称。
抽象数据类型(ABSTRACT DATATYPE,简称ADT):一个数学模型以及定义在该模型上的一组操作,即:数据结构+定义在此结构上的一组操作。
注:<重点>以下有关于算法的时间复杂度第二章:1、线性表的顺序表示和实现线性表的基本操作:①构造一个空顺序表②顺序表的插入算法(2种方法,任选一种)③顺序表的删除算法(2种方法,任选一种)④顺序表的合并算法要求:背算法①初始化线性表:为顺序表分配一个预定义大小的数组空间,并将线性表的初始长度设为0。
算法如下:Status Initlist_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;Return OK;}②插入算法的思想:算法如下:方法1:用指针数组来表示Status ListInsert_sq( sqlist &L, int i, ElemType e) {if ( i<1|| i>L.length+1 ) return ERROR;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;return OK;} // ListInsert_sq方法2:用指针来表示Status listinsert_sq (sqlist &L, int i, elemtype e) {if ( i<1|| i>L.length+1) return ERROR;if ( L.length>=L.listsize) exit( OVERFLOW );q=&(L.elem[i-1]);for( p = & (L.elem[L.length-1]); p>=q; --p )*(p+1)=*p;*q=e;++L.length;return OK;} // ListInsert_sq③线性表的删除——删除第i个元素编写的算法:方法1:用指针数组来表示Status listdelete_sq( Sqlist &L, int i, Elemtype &e) {if (i<1|| i>L.length) return ERROR;e=L.elem[i-1];for ( j=i; j<=L.length-1; ++j)L.elem[ j-1]=L.elem[ j ];--L.length;return OK;}方法2:用指针来表示Status listdelete_sq( Sqlist &L, int i, Elemtype &e) {if(i<1|| i>L.length) return ERROR;p=&(L.elem[i-1]);e=*p;q= &(L.elem[L.length-1]);for(++p; p<=q; ++p)*(p-1)=*p;--L.length;return OK;}④线性表的合并—两个线性表合并成一个编写的算法:Void mergelist_sq(sqlist La, sqlist Lb, 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++;}3、线性表的链式表示和实现(5个)①构造一个空单链表②建立带n个元素的单链表③单链表的查找算法④单链表的插入算法⑤单链表的删除算法要求:•背算法,并能够分析每个算法的时间复杂度;•能够比较顺序表和单链表两种物理结构的区别。
①线性链表的初始化——建一个空链表status Initlist_L(Linklist &L) {// 建立头结点,其next为空L=( Lnode* )malloc( sizeof(Lnode) );return OK;}②建立一个带有n个元素的单链表算法实现:status Createlist_L(Linklist &L, int n) {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;return OK; }}③线性链表的查找——查找单链表的第i个结点,并将其数据域的值赋给变量e。
算法实现:Status Getelem_L(Linklist L, int i, ElemType &e){ p=L->next; j=1;while( p && j<i ) { // 控制L不能是空表,和j<ip=p->next; ++j;}if( !p‖j>i) return error; // 找不到,返回ERRORe=p->data;return OK; //找到第i个结点,返回OK}④线性链表的插入——将单链表的第i个结点之前插入一个结点s,其数据域为值e。
算法实现:Status listinsert_L(Linklist &L, int i, elemtype e){ p=L; j=0;while ( p && j<i-1) {p=p->next; ++j;}if(!p‖j>i-1) return error;s=(Lnode*) malloc ( sizeof (Lnode) );s->data=e;s->next=p->next;p->next=s;return OK;}⑤线性链表的删除——将线性链表的第i个结点删去算法实现:Status listdelete_L(Linklist &L, int i, ElemType &e){ p=L; j=0;while (p->next && j<i-1) { p=p->next; ++j; }if( !(p->next)‖j>i-1 ) return ERROR;p->next=q->next;e=q->data;free(q);return OK;}比较单链表与顺序表(1)顺序表必须分配足够大的连续的存储空间,而链表可以利用零星的存储单元。
(2)单链表逻辑上相邻的元素,其物理位置不一定相邻,元素之间的相邻关系由指针域指示。
(2)在单链表里进行插入、删除运算比在顺序表里容易得多。
(3)对于顺序表,可随机访问任一个元素,而在单链表中,需要顺着链逐个进行查找。
第三章:1、栈1.1 栈的定义1.2 栈的表示和实现顺序栈的算法:创建栈、进栈、出栈、取栈顶元素(背)2、栈的应用举例2.1 数制转换(背)2.2 括号匹配的检验(理解)3、队列3.1 链队列的表示和实现链队列的算法:判断队列是否为空、入队、出队。
背3.2 顺序队列——循环队列顺序队列的物理结构?什么是假溢出?如何解决假溢出?1、栈:限制仅在表尾进行插入或删除操作的线性表。
(1)初始化一个栈——创建栈Status Initstack (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;Return OK;} //initstack(2)进栈(插入新元素)Status push(sqstack &s, selemtype e){if(s.top-s.base>=s.stacksize)exit (OVERFLOW);*S.top++=e;return OK;} //push(3)出栈(删除栈顶元素)status pop(sqstack &s, selemtype &e) {if(s.top==s.base) return ERROR;e=*--s.top;return OK;} //pop(4)取栈顶元素status gettop(sqstack s, selemtype &e) {if (s.top==s.base) return ERROR;e=*(s.top-1);return OK;} //getpop数制转换:算法如下:void conversion ( ) {InitStack (S);scanf ("%d", &N);while (N) {Push(S, N%8);N = N / 8;}while ( !StackEmpty(S) ) {Pop(S, e);printf ( "%d", e );}} // conversion队列的基本操作:判断队列是否为空( QueueEmpty ):Status QueueEmpty( LinkQueue Q ) {if(Q.front == Q.rear) return TRUE;else return FALSE;入队( EnQueue )Status EnQueue ( LinkQueue &Q, QElemType e){p=( QNode* )malloc( sizeof(QNode) );if( !p ) exit(OVERFLOW);p->data=e;p->next=NULL;Q.rear->next=p;Q.rear=p;return OK;}出队(DeQueue )Status DeQueue(LinkQueue &Q, QElemType &e) {if ( Q.front == Q.rear ) return ERROR;p = Q.front->next;e = p->data;Q.front->next = p->next;if (Q.rear == p) Q.rear = Q.front;free(p);return OK; }顺序队列的物理结构:1,队头和队尾指针在队列初始化时,令front=rear=0;2,队头指针指向当前队头元素;3,队尾指针指向当前队尾元素的下一个位置;4,每当插入新的队列尾元素时,在队尾指针处插入新的元素后,队尾指针增1;5,每当删除队列头元素时,取队头指针处的元素值,队头指针增假溢出:当元素被插入到数组中下标最大的位置上之后,队列的空间就用尽了,尽管此时数组的低端还有空闲空间,这种现象叫做假溢出。