数据结构c语言版习题

数据结构c语言版习题

文章目录

  • 第一章 绪论
  • 第二章 线性表
  • 第四章 串
  • 第五章数组和广义表作业
  • 第六章 树与二叉树理论作业
  • 第七章图作业
  • 第八章查找作业

第一章 绪论

一、选择题
1.以下说法正确的是( D )。
A、数据元素是数据的最小单位
B、数据项是数据的基本单位
C、数据结构是带有结构的各数据项的集合
D、一些表面上很不相同的数据可以有相同的逻辑结构
解析:A、B、C不对,正确答案是:数据项是数据的最小单位;数据元素是
数据的基本单位;数据结构是带有结构的各数据元素的集合;D正确,如:windows系统中文件的组织架构图和一个单位的组织架构图,表面上是不相同的数据,但其实都是树形结构。
2.计算机算法指的是解决问题的步骤序列,它必须具备( B ) 这五个特性。
A、可执行性、可移植性、可扩充性、输入、输出
B、可执行性、确定性、有穷性、输入、输出
C、确定性、有穷性、稳定性、输入、输出
D、易读性、稳定性、安全性、输入、输出
解析:一个算法具备的5个重要特性是:有穷性,确定性,可行性,有零个或多个的输入,有1个或多个的输出;
3.设n为某问题的规模,若某算法的时间复杂度为O(n2),则表示该算法的( C )。(北航2019年考研题)
A、执行时间为n。
B、执行时间为n2。
C、执行时间与n2成正比关系。
D、执行时间与n无关。
解析:T(n) = O(f(n))“大O记法”,它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同。
4.程序运行时间函数f(n) = 1000, 下面哪项是用“大O记法”表示的时间复杂度。(B)
A、O(1000)
B、O(1)
C、O(n=1000)
D、O(n)
解析:只要运行时间为常数,均用O(1)表示,即时间复杂度的常数阶为O(1)
5.算法的时间复杂度取决于(D )。
A、问题的规模
B、待处理数据的初态
C、计算机的配置
D、A和B
解析:算法的时间复杂度不仅与问题的规模有关,还与问题的其他因素有关。如某些排序的算法,其执行时间与待排序记录的初始状态有关。为此,有时会对算法有最好、最坏以及平均时间复杂度的评价。
6.在存储数据时,通常不仅要存储各数据元素的值,而且还要存储( D )。
A、数据的处理方法
B、数据的存储方法
C、数据元素的类型
D、数据元素之间的关系
解析:存储数据时,或者用顺序方式来描述数据元素之间的关系,或者用链
式来描述数据元素之间的关系。
7.在数据结构中,与所使用的计算机无关的是数据的(A)结构。
A、逻辑
B、存储
C、逻辑和存储
D、物理
解析:数据的逻辑结构反映的是数据元素之间的逻辑关系,与使用的计算机无关:数据的物理结构,又称存储结构,是指数据在计算机中的表示,它包括数据元素的值和元素的关系,其中数据元素之间的关系在计算机中主要有顺序存储结构和链式存储结构两种。
8.在下面的程序段中,对x的赋值的语句频度为(C  )
for(i=0;i for(j=0;j A、O(2n) 
B、O(n)
C、O(n*n)
D、O(log2n)
解析:外循环的循环次数为n, 内循环的循环次数为n, 所以两个循环嵌套起来,时间复杂度为:O(n2)。
9.在数据结构中,从逻辑上可以把数据结构分成(C)。
A、动态结构和静态结构
B、紧凑结构和非紧凑结构
C、线性结构和非线性结构
D、内部结构和外部结构
解析:线性表属于线性结构,集合、树和图属于非线性结构。
10.下面这段描述不能满足算法的特性,请问它违反了算法的哪条特性?( B )
void exam()
{
int n = 2;
while (n % 2 == 0)
n = n + 2;
printf(“%d\n”, n);
}
A、算法的确定性
B、算法的有穷性
C、算法的可行性
D、以上三条都违反了
解析:其中有一个死循环,违反了算法的有穷性特征。
11.数据结构的逻辑结构被形式化地定义为一个二元组(D,S),其中D是(① )的有限集合,S是D上( ② )的有限集合。(B)
A、数据 映射
B、数据元素 关系
C、算法 操作
D、数据操作 存储
解析:举个例子便于大家理解:如包含6个元素(a1,a2,a3,a4,a5,a6)的一维数组可以用这样的二元组形式化的描述为:D={a1,a2,a3,a4,a5,a6},S={|i=1,2,3,4,5}。
12.下面的程序段中, n为正整数,则最后一行的语句频度在最坏情况下是(D  )

for(i=n-1;i>=1;i–)
for(j=1;j<=i;j++)
if (A[j]>A[j+1])
A[j]与A[j+1]对换;
A、O(n)
B、O(nlog2n)
C、O(n^3)
D、O(n^2)
解析;最后一行的语句频度在最坏情况下对应的情况是,每次if的条件都满足,从程序可看出,内循环的循环次数和外循环的循环变量有关系,f(n)=(n-1)+(n-2)+…+1=(n-1+1)(n-1)/2=(n2-n)/2。根据时间复杂度常系数可忽略和低次项可忽略的规则,可知时间复杂度为O(n2)。
13.下面程序段的时间复杂度为( C )。(2014年全国考研题)
count = 0;
for (k=1; k<=n; k
=2)
for(j=1; j<=n; j++)
count++;
A、O(log2n)
B、O(n)
C、O(nlog2n)
D、O(n^2)
解析:分开来看,若外循环中的语句执行频度是f(n), 则,
2f(n)<=n; f(n)<=log2n; 取最大值f(n)= log2n;
又内循环的循环次数为n, 所以两个循环嵌套起来,时间复杂度为,O(nlog2n)
二、简答题
1.2020年注定是让人难忘的一年,这一年开头中国就备受新冠病毒的侵扰,让全国人民待在家里过了一个与众不同的春节,关注疫情数据也成了大家每天的“必修课”。作为重灾区的湖北,在2020年3月18日新增确诊首次清零。表1_1是2020年3月19日在疫情实时更新系统中查到的部分省份的数据,请描述其中的数据元素,数据项,数据对象和数据。
数据结构c语言版习题_第1张图片
答:数据元素:一个地区的疫情记录。如:(湖北,0,67800,57681,3130)。
数据项:湖北,0,67800,57681,3130均是该数据元素的数据项。
数据对象:如果要研究的是国内的疫情,那么数据对象就是国内各地区的疫情记录的集合。
数据:如果要研究的是全球的疫情,那么数据就是全球各国家各地区的疫情记录的集合。
2.分析下面完成冒泡排序的算法的时间复杂度和空间复杂度。
void bubbleSort(int array[], int n)
{
int i, j, tmp,flag;
if (n <= 1) return;
for (i = n-1; i > 0; i-- ){
flag = 0; // 变量flag用来标记本趟排序是否发生了交换
for (j = 0; j < i; j++){
if (array[j] > array[j+1]){
tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
flag = 1; // 没发生交换flag=0不变, 发生了交换flag变为1
}
}
if (flag == 0) return; //
}
}
答案:
该冒泡排序算法的时间复杂度为T(n)=O(n^2)
该冒泡排序算法的空间复杂度为S(n)=O(1)
解析:时间复杂度的计算
因为计算时间复杂度时,常数项可以忽略,所以可选取最内层循环中的关键字交换操作为基本操作,又因为输入数据的情况不一样,基本操作的执行频度也不一样,所以以最坏情况来计算本算法的时间复杂度。本算法的最坏情况为待排序列为逆序,此时,对于外层循环的每次执行,内层循环中if语句的条件均成立,即基本操作的执行次数为n-i,i的取值为1~n-1。因此,基本操作总的执行次数为(n-1+1)(n-1)/2=n(n-1)/2,其中常系数和低次项可以忽略。
所以,该冒泡排序算法的时间复杂度为T(n)=O(n2)。
空间复杂度的计算
由算法代码可以看出,算法在运行过程中临时占用的存储空间只有一个temp,与问题规模n没有关系,所以该冒泡排序算法的空间复杂度为S(n)=O(1)。
以下是有关用“指针”操作“三元组”的相关程序,请将程序中缺少的语句补充完整。(请注意:答案中不要有多余的空格)

# include

# include

# define OK 1

# define ERROR 0

# define OVERFLOW -2 

typedef int Status;

typedef float ElemType;

typedef ElemType *Triplet; // 声明Triplet为ElemType指针类型 

 

//三元组的初始化

Status initTriplet(Triplet &T, ElemType v0, ElemType v1, ElemType v2)

{

    T = (       ElemType * Triplet             )malloc(3*sizeof(ElemType)); // 第一空

    if (              T==NULL !T      )   // 第二空

    {

        printf("分配内存失败!");

        exit(OVERFLOW);

    }

    T[0] = v0;

    T[1] = v1;

    T[2] = v2;

    return OK;

}

//释放内存,退出系统, 注意:动态分配内存需要及时释放内存空间

void destroyTriplet(Triplet &T)

{

          free(T)                   ; // 第三空

    printf("分配内存已释放!");

     exit(0);

}

// 用e获取T的第i(1~3)个元素的值, 

Status getElem(Triplet T, int i, ElemType &e)

{

    if (i < 1 || i > 3)

        return ERROR;

    else                e=T[i-1]       ; // 第四空

        return OK;

}

// 置T的第i元的值为e 

Status putElem(Triplet &T,int i,ElemType e)

{

    if (i < 1 || i > 3)

        return ERROR;

    else                 T[i-1]=e       ; // 第五空

        return OK;

}

int main()

{

    Triplet T;

    Status flag;

    ElemType v0, v1, v2, e;

    

    printf("请进入三元组的三个值v0,v1,v2:\n"); 

    scanf("%f%f%f",         &v0,&v1,&v2                      ); //第6空

    // 初始化三元组 

    initTriplet(T,            v0,v1,v2           ); //第7空

    printf("调用初始化函数后,T的三个值为:%.1f,%.1f,%.1f\n", T[0], T[1], T[2]);

    // 请调用函数获得T的第2元的值 

                            getElem(T,2,e)       ; // 第8空

    printf("三元组第2元的值为:%.1f\n",e); 

    // 请调用函数修改T的第2元的值为56.7

                                    putElem(T,2,56.7)        ; // 第9空

    // 再次输出T的第2元的值 

    printf("三元组第2元的值改成了:%.1f\n",T[1]); 

    // 销毁三元组

                      destroyTriplet(T)                            ; // 第10空

    return 0;

} 

第二章 线性表

1.在双向循环链表中,在p指针所指的结点后插入q所指向的新结点,其修改指针的操作是( C )。
A、p->next=q; q->prior=p; p->next->prior=q; q->next=q;
B、p->next=q; p->next->prior=q; q->prior=p; q->next=p->next;
C、q->prior=p; q->next=p->next; p->next->prior=q; p->next=q;
D、q->prior=p; q->next=p->next; p->next=q; p->next->prior=q;
解析:双向循环链表的操作,与单链表相似,重接链条,语句有次序
2.在双向链表存储结构中,删除p所指的结点时须修改指针( A )。
A、p->next->prior=p->prior; p->prior->next=p->next;
B、p->next=p->next->next; p->next->prior=p;
C、p->prior->next=p; p->prior=p->prior->prior;
D、p->prior=p->next->next; p->next=p->prior->prior;
解析:双向链表的删除操作,双向链表的操作,注意语句的次序
3.在单链表中,要将s所指结点插入到p所指结点之后,其语句应为( D )。
A、s->next=p+1; p->next=s;
B、(*p).next=s; (*s).next=(*p).next;
C、s->next=p->next; p->next=s->next;
D、s->next=p->next; p->next=s;
解析:插入后重新接链条:s->next=p->next; p->next=s; 语句的次序不能改变
4.设一个有序的单链表中有n个结点,现要求插入一个新结点后使得单链表仍然保持有序,则该操作的时间复杂度为( D)。
A、o(log2n)
B、o(1)
C、o(n^2)
D、o(n)
解析:该题主要完成的是查找新元素应该插入的位置,所以查找的时间复杂度是该题的时间复杂度,为o(n)
5.`设有一个正整数序列组成的有序单链表,试编写能实现下列功能的算法:确定在序列中比正整数x大的数有几个。

#include

#include

//定义单链表结构

typedef struct LNode{

int data;

struct LNode *next;

}LNode,*LinkList;

//创建空的单链表

LinkList creat_head(){

 LinkList p;

 p=(LinkList)malloc(sizeof(LNode));

­­­­ _______(1)______________;//p->next=NULL
return§;

}

//输出单链表

void print_list(LinkList &L){

   LinkList p;

   for(p=L->next;p!=NULL;)

   { 

      printf("%d",____(2)______);//p->data

      _____(3)__________;//p=p->next

   }

}

// 生成单链表

void creat_list(LinkList &L,int n){

LinkList p,q; 

 int i; 

 p=L; 

 for(i=1;i<=n;i++){ 

   q=(LinkList)malloc(sizeof(LNode)); 

   printf("data:"); 

   scanf("%d",&q->data);

   q->next=NULL;

p->next=q;

  _____(4)_______;//p=q
}   

print_list(L); //显示创建好的链表元素

}

//计算函数

int count(LinkList L,int x)

{

int num=0;

LNode *p;

p=L->next;

while(p&&p->data<=x)

  ______(5)_________;//p=p->next

while(p){

if((6)__)//p->data>x {

num++;

__(7) ____;//p=p->next
}

else{

 p=p->next;

}

}

return num;

}

main(){

int i,num,n;

LinkList L;   

_____(8)________;      //创建链表头结点//L = creat_head()

printf(“输入链表的结点个数 n=”);

scanf("%d",&n);   

______(9)__________;   //创建n个结点的单链表  //creat_list(L,n)

 printf("输入一个数:");

 scanf("%d",&i);

 printf("%d",____(10)________);//count(L,i)

}`
6.将两个各有n个元素的有序表归并成一个有序表,其最少的比较次数是( A)。
A、n
B、2n-1
C、2n
D、n-1
解析:当第一个有序表中所有的元素都小于(或大于)第二个表中的元素,只需要用第二个表中的第一个元素依次与第一个表的元素比较,总计比较n次。
7.在一个长度为n的顺序表中,在第i个元素(1≤i≤n+1)之前插入一个新元素时须向后移动( B )个元素
A、n-i
B、n-i+1
C、n-i-1
D、i
解析:在第i个位置插入元素,操作时需移动的元素从第i个元素到最后一个元素
8.在n个结点的顺序表中,算法的时间复杂度是O(1)的操作是(A )。
A、访问第i个结点(1≤i≤n)和求第i个结点的直接前驱(2≤i≤n)
B、在第i个结点后插入一个新结点(1≤i≤n)
C、删除第i个结点(1≤i≤n)
D、将n个结点从小到大排序
解析:在顺序表中插入一个结点的时间复杂度都是O(n^2),排序的时间复杂度为O(n ^2)或O(nlog2n)。顺序表是一种随机存取结构,访问第i个结点和求第i个结点的直接前驱都可以直接通过数组的下标直接定位,时间复杂度是O(1)。
9.创建一个包括n个结点的有序单链表的时间复杂度是(C )。
A、O(1)
B、O(n)
C、O(n ^2)
D、O(nlog2n)
解析:单链表创建的时间复杂度是O(n),而要建立一个有序的单链表,则每生成一个新结点时需要和已有的结点进行比较,确定合适的插入位置,所以时间复杂度是O(n ^2)
10.已知L是带表头结点的单链表,删除第一个元素结点的语句是(B )。
A、L = L->next;
B、L-> next = L-> next -> next;
C、L = L;
D、L-> next = L;
解析:删除图中的第一个元素a1,则头指针的next域(L->next)指向的是a1的下一个元素,a1元素的位置可表示为L-> next,a1的下一个元素为L-> next->next,所以答案为L-> next = L-> next -> next;
在这里插入图片描述

11.若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用( A )存储方式最节省时间。
A、顺序表
B、双链表
C、带头结点的双循环链表
D、单循环链表
解析:顺序存储结构的特点是随机存取(时间复杂度为常数阶),在顺序表的最后进行插入和删除不需要移动元素,时间复杂度是常数阶。
12.设计一个函数Max(LinkList L),实现通过一趟遍历确定单链表中值最大的结点,且返回该值。

float Max (LinkList L ){ 

if(L->next==NULL) return NULL; 

pmax=L->next; //假定第一个结点中数据具有最大值

p=L->next->next; 

while(p != NULL ){//如果下一个结点存在

if(p->data > pmax->data)pmax=p; //如果p的值大于pmax的值,则重新赋值

p=p->next;//遍历链表

} 

return pmax->data;

} 
以下程序是采用单链表存储结构实现线性表的插入操作,阅读程序,补全代码

#include

#include

typedef  struct LNode{

int data;  

struct LNode *next;

}LNode,*LinkList;

 

void creat_list(LinkList &L,int); //创建链表

 

void insert_list(LinkList &L,int,int ); //插入数据

 

void print_list(LinkList &L);//显示数据  

 

//尾插法创建单链表

void creat_list(LinkList &L,int n)

{  

  LinkList p,q;

//创建头结点

   L=(LinkList)malloc(sizeof(LNode));

  ——(1)—— ;//L->next=NULL

   int i;  

   p=L;    

   for(i=1;i<=n;i++)  

  {  

     q=(LinkList)malloc(sizeof(LNode));  

     printf("data:");  

     scanf("%d",&——(2)——);//q->data

     q->next=NULL;

     ——(3)——);//p->next=q

     p =q;

   }  

 }

 

//插入新数据

void insert_list(LinkList &L,int x,int i )

{  

 

   int j=0;  

   LinkList p,s;

   p=L;

   while((p!=NULL)&&(jnext

       j++;

   }

   if(p==NULL|| j >i-1)  

   {

    printf("插入点位置错误!\n");

    exit(0);

   }   

   s=(LinkList)malloc(sizeof(LNode));

  ——(5)——;//s->data=x

   s->next=p->next;

 ——(6)——;//p->next=s
   print_list(L);

 }

 

//显示数据值

void print_list(LinkList &L)

{  

   LinkList p;

  ——(7)——;//p=L->next

   while(p!=NULL)

  {  

       printf("%d,",p->data);  

      ——(8)——;//p=p->next
   }

}  

main()

{  

 LinkList L,p;  

 int n;  

 int x,i;  

 printf("输入链表的结点个数 n=");

 scanf("%d",&n);    

——(9)——;   //创建n个结点的单链表//creat_list(L,n)

 printf("\n*****************************************************\n");

 printf("输入要插入的元素值 x=");

 scanf("%d",&x);

 printf("\n输入要插入的位置 i=");

 scanf("%d",&i);

——(10)——;   //向链表的第i个元素前插入数据x//insert_list(L,x,i)

  system("pause");    

}

第四章 串

1.串是一种特殊的线性表,其特殊性体现在( B)。
A、可以顺序存储
B、数据元素是字符
C、可以链式存储
D、数据元素没限制
解析:串的特殊性是数据元素是字符
2.下面关于串的的叙述中,( B )是不正确的?
A、串是字符的有限序列
B、空串是由空格构成的串
C、模式匹配是串的一种重要运算
D、串既可以采用顺序存储,也可以采用链式存储
解析:空串的长度为0,空格串是有元素的(空格符),长度不为0
3.串的长度是指( B)。
A、串中所含不同字母的个数
B、串中所含字符的个数
C、串中所含不同字符的个数
D、串中所含非空格字符的个数
解析:串中字符的数目称为串的长度
4.( D )是C语言中“abcd321ABCD”的子串。
A、abcd
B、321AB
C、“abcABC”
D、“21AB”
解析:C语言中规定字符串是用一对双引号括起来的字符序列。
5.设有两个串p和q,求q在p中首次出现的位置的运算称做(B )。
A、连接
B、模式匹配
C、求子串
D、求串长
解析:寻找q在p中首次出现的位置的运算称作模式匹配
6.串“ababaaabab”的next数组为( C )。
A、0123456789
B、0121211112
C、0112342234
D、0123012322
解析:按照next数组的算法依次计算即可
7.SubString( sub, “structure”, 4, 3)的结果是( “uct” )。注意:字符串用双引号括起来
解析:该含义是从第4个位置截取3个元素结果为uct
8.S = “stg” ,T =“rin”,则执行 StrInsert(S, 3, T) 之后得到( “string” )。注意:字符串用双引号括起来
解析:该函数的意义是在S串的第3个位置插入T串结果为string
9.INDEX(“DATASTRUCTURE”, “C”)=9____。(位置从1开始)
解析:该函数是查找str在主串中的索引位置
10.`以下算法是采用BF算法实现字符串的模式匹配过程,请补全代码(位置从0开始)。

int mate(char *a, char *c){

int i=0,j=0;

while(i

   if(___(1)____)//a[i]==c[j]
   {

       i++;

       j++;

}

else{

   _____(2)____;//i=i-j+1
   j=0;

}

}

if(j==strlen©){

   return i-strlen(c)+1;

}

return 0;

}

int main(int argc, char *argv[]) {

int n=mate(“abc”,“a”);

printf("%d",(3));//n

return 0;

}`

采用堆分配存储方式实现在串S的第pos个位置前插入串T,补全代码

//存储结构定义

typedef struct {

    char *ch;    

    int  length;  

 } HString

int StrInsert(HString &S,int pos,HString T){  

  int i;

  if (pos<1||pos>S.length+1) return 0;

  if (T.length){

     if (!(S.ch=(char*) realloc(S.ch,(S.length+T.length)*sizeof(char))))

     exit(OVERFLOW);

     for (i=S.length-1;i>=pos-1;--i){

        ___(1)_________ ;//S.ch[i+T.length]=S.ch[i]

  }

  for (i=0; i<=T.length-1;i++)

  _______(2)___________;//S.ch[pos-1+i]=T.ch[i]

  _______(3)_____________;//S.length+=T.length
  } return OK;

}

第五章数组和广义表作业

1.假设以行序为主序存储二维数组A=array[1…100,1…100],设每个数据元素占2个存储单元,基地址为10,则LOC[5,5]=( B )。
A、808
B、818
C、1010
D、1020
解析:以行序为主,则LOC[5,5]=[(5-1)*100+(5-1)]*2+10=818。
2.设有数组A[i,j],数组的每个元素长度为3字节,i的值为1到8,j的值为1到10,数组从内存首地址BA开始顺序存放,当用以列为主存放时,元素A[5,8]的存储首地址为(B )。
A、BA+141
B、BA+180
C、BA+222
D、BA+225
习题解析:以列序为主,则LOC[5,8]=[(8-1)*8+(5-1)]*3+BA=BA+180。
3.多维数组之所以有行优先顺序和列优先顺序两种存储方式是因为(D )。

A、数组的元素处在行和列两个关系中
B、数组的元素必须从左到右顺序排列
C、数组的元素之间存在次序关系
D、数组是多维结构,内存是一维结构
习题解析:由于存储单元是一维的结构,而数组可能是多维的结构,所以用一组连续存储单元存放数组的数据元素就有次序约定问题。因此多维数组有行优先顺序和列优先顺序两种存储方式,因此答案选择D。
4.设二维数组A[1… m,1… n](即m行n列)按行存储在数组B[1… m*n]中,则二维数组元素A[i,j]在一维数组B中的下标为( A)。
A、(i-1)n+j
B、(i-1)n+j-1
C、i
(j-1)
D、j
m+i-1
习题解析:特殊值法。取i=j=1,易知A[1,1]的的下标为1,四个选项中仅有A选项能确定的值为1,故选A。
5.二维数组A的每个元素是由10个字符组成的串,其行下标i=0,1,…,8,列下标j=1,2,…,10。若A按行先存储,元素A[8,5]的起始地址与当A按列先存储时的元素( B )的起始地址相同。设每个字符占一个字节。
A、A[8,5]
B、A[3,10]
C、A[5,8]
D、A[0,9]
习题解析:设数组从内存首地址M开始顺序存放,若数组按行先存储,元素A[8,5]的起始地址为:M+[(8-0)*10+(5-1)]*1=M+84;若数组按列先存储,易计算出元素A[3,10]的起始地址为:M+[(10-1)*9+(3-0)]1=M+84。故选B。
6.一维数组的逻辑结构是__、
线性结构___________,存储结构是__顺序结构 顺序存储结构___________。
习题解析:一维数组{a0,a1,…,an-1}是n个相同类型数据元素构成的有限序列,线性表是具有相同特性的数据元素的一个有限序列。所以一维数组的逻辑结构是线性结构。数组中的有限序列存储在一块连续的内存单元中,所以一维数组的存储结构是顺序结构
7.二维数组A[10][20]采用列序为主方式存储,每个元素占一个存储单元,且A[0][0]的地址是200,则A[6][12]的地址是(326     )
习题解析:采用列主序时,LOC(A[6][12])=LOC(A[0][0]+(12
10+6)*1)=326
8.设数组a[1…50,1…80]的基地址为2000,每个元素占2个存储单元,若以行序为主序存储,则元素a[45,68]的存储地址为( 9174 )。
习题解析:Loc(ai,j)=2000+((45-1)×80+(68-1))×2=9174
9.数组A中,每个元素A[i,j]的长度均为32个二进制位,行下标从-1到9,列下标从1到11,从首地址S开始连续存放主存储器中,主存储器字长为16位。求:
① 存放该数组所需多少单元?( 242 )
② 存放数组第4列所有元素至少需多少单元?( 22 )
③ 数组按行存放时,元素A[7,4]的起始地址是多少?( S+182 )
④ 数组按列存放时,元素A[4,7]的起始地址是多少?( S+142 )
习题解析:
每个元素32个二进制位,主存字长16位,故每个元素占2个字长,行下标可平移至1到11。
(1)242。该数组包括的元素个数总计有:(9-(-1)+1)×(11-1+1)=121,因为每个元素占2个字长,存放该数组所需单元总计为121×2=242个。
(2)22。第4列包括的元素个数总计有(9-(-1)+1)=11,每个元素占2个字长,因此,存放第4列所有元素至少需单元为121×2=242个。
(3)S+182。LOC=S+((7-(-1))×(11-1+1)+(4-1))×2= S+182。
(4)S+142。LOC=S+((7-1) ×(9-(-1)+1) +(4-(-1))) ×2= S+142。
10.对特殊矩阵采用压缩存储的主要目的是(D )。
A、表达变得简单
B、对矩阵元素的存取变得简单
C、去掉矩阵中多余的元素
D、减少不必要的存储空间
11.对n阶对称矩阵压缩存储时,需要表长为( C )的顺序表。
A、n/2
B、n2/2
C、n(n+1)/2
D、n(n-1)/2
习题解析:对称矩阵只需要存储一半元素,即存储其下(上) 三角(包括对角线)中的元素,总计包括元素个数为1+2+3+…+(n-1)+n=n(n+1)/2。
12.稀疏矩阵一般的压缩存储方法有两种,即(C )。
A、二维数组和三维数组
B、三元组和散列
C、三元组和十字链表
D、散列和十字链表
13.下面说法不正确的是( A )。
A、广义表的表头总是一个广义表
B、广义表的表尾总是一个广义表
C、广义表难以用顺序存储结构
D、广义表可以是一个多层次的结构
习题解析:任何一个非空广义表的表头元素可能是原子元素,也可能是表元素,但其表尾元素一定是广义表。由于广义表中的数据元素既可以是单个元素,也可以是子表,因此广义表难以用顺序存储结构来表示,通常用链式存储结构来表示。表中的每个元素可用一个结点来表示,广义表中有两类结点:一类是单个元素结点,一类是子表结点。
14.广义表((a,b,c,d))的表头是(C)。
A、a
B、( )
C、(a,b,c,d)
D、(b,c,d)
习题解析:
表头为非空广义表的第一个元素,可以是一个原子,也可以是一个子表,((a,b,c,d))的表头为一个子表(a,b,c,d)。
15.广义表((a,b,c,d))的表尾是(B )。
A、a
B、( )
C、(a,b,c,d)
D、(b,c,d)
习题解析:表尾为除去表头之外,由其余元素构成的表,表尾一定是个广义表,((a,b,c,d))的表尾为空表( )。
16.设有广义表D=(a,b,D),则其长度为( B)。
A、1
B、3
C、∞
D、5
习题解析:广义表的长度是指广义表中所含元素的个数。

第六章 树与二叉树理论作业

1.由3个结点可以构造出多少种不同的二叉树?(D)
A、2
B、3
C、4
D、5
数据结构c语言版习题_第2张图片
2.一棵完全二叉树上有1001个结点,其中叶子结点的个数是(D)。
A、250
B、500
C、254
D、501
习题解析:答案解析:解释:设度为0结点(叶子结点)个数为A,度为1的结点个数为B,度为2的结点个数为C,有A=C+1,A+B+C=1001,可得2C+B=1000,由完全二叉树的性质可得B=0或1,又因为C为整数,所以B=0,C=500,A=501,即有501个叶子结点。
3.深度为h的满m叉树的第k层有(A)个结点。(1= A、m^(k-1)
B、m^k-1
C、m^(h-1)
D、m^h-1
习题解析:深度为h的满m叉树共有m ^ h-1个结点,第k层有 m^(k-1)个结点。
4.一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足(C)。
A、所有的结点均无左孩子
B、所有的结点均无右孩子
C、只有一个叶子结点
D、是任意一棵二叉树
答案解析:因为先序遍历结果是“中左右”,后序遍历结果是“左右中”,当没有左子树时,就是“中右”和“右中”;当没有右子树时,就是“中左”和“左中”。则所有的结点均无左孩子或所有的结点均无右孩子均可,所以A、B不能选,又所有的结点均无左孩子与所有的结点均无右孩子时,均只有一个叶子结点,故选C。
5.对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用(C)遍历实现编号。
A、先序
B、中序
C、后序
D、从根开始按层次遍历
答案解析:根据题意可知按照先左孩子、再右孩子、最后双亲结点的顺序遍历二叉树,即后序遍历二叉树。
6.在树中,若结点A有4个兄弟,而且B是A的双亲,则B的度为(C )
A、3
B、4
C、5
D、6
答案解析:B有5个孩子,故B的度为5.
7.若树T中度为1、2、3、4的结点个数分别为4、3、2、2,则T中叶子结点的个数为(B )。
A、13
B、14
C、15
D、24
答案解析:树中的分支数为14+23+32+42=24,树中的结点总数为24+1=25,叶子结点个数为25-4-3-2-2=14
8.以下属于前缀编码的是(C )。
A、{0,1,01,010,110}
B、{01,00,10,001,110,101}
C、{0,1101,1110,1100,1111}
D、{00,01,10,11,101}
答案解析:前缀编码指的是,任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀。本题中只有C选项符合前缀编码的定义。
9.引入二叉线索树的目的是(A)。
A、加快查找结点的前驱或后继的速度
B、为了能在二叉树中方便的进行插入与删除
C、为了能方便的找到双亲
D、使二叉树的遍历结果唯一
答案解析:为了保存二叉树遍历过程中得到的每个结点的前驱和后继信息,引入了线索二叉树,以加快查找结点的前驱或后继的速度。
10.设F是一个森林,B是由F变换得的二叉树。若F中有n个非终端结点,则B中右指针域为空的结点有( C )个。
A、n−1
B、n
C、n + 1
D、n + 2
答案解析:n个非终端结点即表示森林中有n颗二叉树,转换成二叉树中,这n个结点的左子树中会有n个右指针域为空的结点,另外n个非终端结点中的最后一个结点的右指针域也为空,共n+1个。
11.给定二叉树的先序、中序和后序遍历序列中的两个,就可以唯一确定一棵二叉树。(错误)
答案解析:二叉树的存储结构有顺序存储结构和链式存储结构
12.定二叉树的先序、中序和后序遍历序列中的两个,就可以唯一确定一棵二叉树。(同上
13.在线索二叉树中每个结点通过线索都可以直接找到它的前驱和后继。(错误)
答案解析:线索二叉树中的有左右子树的结点,它们的指针指向其左右子树,并没有指向前驱或后继,因此这些结点是不能直接找到它的前驱和后继的。
14.将一棵树转成二叉树,根结点一定没有右子树。(正确
习题解析:树转换成二叉树按照“左孩子,有兄弟”结构存储,由于一棵树没有兄弟,所以右子树为空。
15.着信息时代的到来,信息越来越多,如何压缩信息已经是重要课题。哈夫曼编码是一种无损压缩编码方式,经常应用于数据压缩。现有一段通信的电文仅由8个字母A、B、C、D、E、F、G、H组成,字母在电文中出现的频率分别为0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10。试为这8个字母设计合适的编码,使得电文的长度最短。
规定(1)在构造哈夫曼树时,左子树结点的权值小于右子树结点的权值;
(2)进行哈夫曼编码是,左分支标0,右分支标1;
答案:请将每个字母的哈夫曼编码填在下面的空中
(1): 1010
(2): 00
(3):10000
(4):1001
(5):11
(6):10001
(7):01
(8):1011
答案解析:先将概率放大100倍,以方便构造哈夫曼树。
w={7,19,2,6,32,3,21,10},按照哈夫曼算法可以得出相应的哈夫曼编码
16.以下程序的功能是按照先序次序创建二叉树,并对二叉树中序遍历,输出中序遍历的结果,请将程序中缺少的语句补充完整。

#include
#include
#include
#include
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define STACK_INIT_SIZE 50
typedef int Status;
typedef char ElemType;
//树节点
typedef struct BiTNode{
ElemType data; // 1                            
struct BiTNode *lchild,*rchild;
}BiTNode, *BiTree;
//栈结构
typedef struct{   
      BiTNode *base;       
      BiTNode *top;       
      int stacksize;       
}SqStack;
//初始化栈
Status InitStack(SqStack &s) 
{  //过程略,此处不做答
} 
//取栈顶元素
BiTNode *Top (SqStack s)
{  //过程略,此处不做答
//入栈
Status Push(SqStack &s, BiTree e)
{ 
//过程略,此处不做答
} 
//出栈
Status  Pop(SqStack &s)
{  //过程略,此处不做答
} 
//判空栈
int StackEmpty(SqStack S) 
{//过程略,此处不做答
} 
//先序创建二叉树
BiTree Create(BiTree T)
{
       ElemType ch;
       ch=getchar();//2                        
       if(ch=='#')
       T=NULL;
       else
       {
      T=(BiTNode *)malloc(sizeof(BiTNode));//3
      T->data=ch; T -> data=ch; T->data= ch; T ->data=ch; T ->data=ch; T -> data=ch;                         /*根结点赋值
      T->lchild=Create(T->lchild);        
      T->rchild=Create(T->rchild);//5                                                         /*先序创建右子树
       }
       return T;
 } 
//二叉树的中序非递归遍历算法:
void IneOrderNoRec(BiTree BT)
{
  SqStack S;
  InitStack(S);
  BiTree p=BT;//6       
 while((NULL!=p)||!StackEmpty(S))
  { // 找到最左下的结点
if(NULL!=p)
    {      
Push(S,p);    //7    /*压栈
     p=p->lchild;
    }         
       else
    {//根指针退栈,访问根结点
      p=Top(S);
      Pop(S);
  printf("%c",p->data);//8  /*访问根结点
p=p->rchild;
    }
  }
}
//主函数
main() 
{
  BiTree T;
  SqStack S;
  int flag;
  printf("请按先序次序输入二叉树节点的值(一个字符),用#表示空树:\n");      
T=Create(T);  //9             /*先序创建二叉树
  printf("\n二叉树的中序非递归遍历结果:"); 
IneOrderNoRec(T);   //10                   /*中序非递归遍历
  }

第七章图作业

1.用邻接表表示图进行广度优先遍历时,通常借助( B )来实现算法。
A、栈
B、队列
C、散列表
D、链表
习题解析:广度优先搜索是一种分层的搜索过程,每向前走一步可能访问一批顶点,为了实现逐层访问,算法中使用了一个队列,用以记忆正在访问的这一层和上一层的顶点,以便于向下一层访问。
2.下列哪一种图的邻接矩阵是对称矩阵(A )。
A、无向图
B、其它都不对
C、AOV网
D、有向图
习题解析:图的邻接矩阵概念
3.在AOV网中,该图的拓扑序列中,若顶点Vi在顶点Vj之前,则下列情形不可能出现的是(D )。
A、图中有弧
B、图中有一条从Vi到Vj的路径
C、图中没有弧
D、图中有一条从Vj到Vi的路径
习题解析:图的邻接矩阵概念
4.下列关于最小生成树的说法中,正确的是(A) l、最小生成树的代价唯一、最小生成树的代价唯一 Ⅱ、所有权值最小的边一定会出现在所有的最小生成树中 Ⅲ、使用普里姆(Prim)算法从不同顶点开始得到的最小生成树一定相同 Ⅳ、使用普里姆算法和克鲁斯卡尔(Kruskal)算法得到的最小生成树总不相同
A、仅Ⅰ
B、仅Ⅱ
C、仅Ⅰ、Ⅲ
D、仅Ⅱ、Ⅳ
5.在无向图G的邻接矩阵A中,若A[i][j]等于1,则A[j][i]等于( A)。
A、1
B、0
C、不确定
D、无穷大
习题解析:无向图的邻接矩阵是对称矩阵,A[i][j]=1,所以A[j][i]=1。
6.数据结构c语言版习题_第3张图片
D
习题解析:每次输出入度为0的点,输出之后从原图删去该点以及该点为起点的边,然后继续输出入度为0的点,知道输出全部顶点。
7.如果一个有向无权图图采用邻接矩阵表示,计算第i个结点的入度的方法是(B)。
A、该邻接矩阵第 i 行中为1的个数
B、该邻接矩阵第 i 列中为1的个数
C、无法确定
D、该邻接矩阵第 i 行中为1的个数加该邻接矩阵第 i 列中为1的个数
习题解析:有向无权图的邻接矩阵中,行中为1的个数是该结点的出度,列中为1的个数是该结点的入度。
8.数据结构c语言版习题_第4张图片
f,d,e
数据结构c语言版习题_第5张图片
9.数据结构c语言版习题_第6张图片
1、f,g,2 g,f,2
2、e,f,3 f,e,3 a,c,3 c,a,3
3、e,f,3 f,e,3 a,c,3 c,a,3
4、a,b,4 b,a,4 d,h,4 h,d,4
5、a,b,4 b,a,4 d,h,4 h,d,4
6、b,d,5 d,b,5 c,d,5 d,c,5 d,g,5 g,d,5 c,h,5 h,c,5
7、b,d,5 d,b,5 c,d,5 d,c,5 d,g,5 g,d,5 c,h,5 h,c,5
数据结构c语言版习题_第7张图片
10.数据结构c语言版习题_第8张图片
1、28
2、v3 V3
3、v5 V5
4、v8 V8
5、v9 V9
6、v10 V10
7、v11 V11
数据结构c语言版习题_第9张图片
实验填空题(注意大小写要严格按规定写,语法按照C语言语法完成):

#define MAX_VEX_NUM 20
图的邻接矩阵定义如下:
typedef struct
{
int vertex[MAX_VEX_NUM]; //顶点信息
int arcs[MAX_VEX_NUM][MAX_VEX_NUM];//边信息
int vex_num, arc_num;
} Mgraph;
int LocateVex(Mgraph g, int v) //确定v在g中位置
{ 
int i;
for (i = 0; i < g.vex_num; ++i)
{ 
if(g.vertex[i]==v)
return i; 
} 
return -1;
}
创建无向不带权图的算法如下:
void create_UDG(Mgraph &g)
{ 
int i, j, k; 
int v1, v2; 
printf("请输入顶点个数,边的个数:\n");
scanf("%d,%d",     &g.vex_num   ,&g.arc_num); 
printf("请输入顶点信息:\n");
for (i = 0; i < g.vex_num; ++i) 
scanf("%d", &g.vertex[i]); //构造顶点向量
for (i = 0; i < g.vex_num; ++i) //初始化邻接矩阵
for (j = 0; j < g.vex_num; ++j) 
g.arcs[i][j] = 0  ;
printf("请输入边的信息:\n"); 
for (k = 0; k < g.arc_num; ++k) 
{
//构造邻接矩阵
scanf("%d,%d",&v1, &v2); //输入一条边依附的顶点
i = LocateVex(g, v1); //确定v1和v2在G中位置
j = LocateVex(g, v2 ); 
if(i == -1 || j==-1) return;
g.arcs[i][j] = 1; 
g.arcs[j][i] =  g.arcs[i][j] ;
}
}
int main()
{ 
Mgraph g; 
 create_UDG(g) ;//创建图
out_UDG(g); 
return 0;
}

第八章查找作业

1.对n个元素的表做顺序查找时,若查找每个元素的概率相同,则平均查找长度为( C)。
A、(n-1)/2
B、n/2
C、(n+1)/2
D、n
习题解析:总查找次数N=1+2+3+…+n=n(n+1)/2,则平均查找长度为N/n=(n+1)/2。
2.设哈希表长为14,哈希函数是H(key)=key%11,表中已有数据的关键字为15,38,61,84共四个,现要将关键字为49的元素加到表中,用二次探测法解决冲突,则放入的位置是( D )。
A、8
B、3
C、5
D、9
习题解析:关键字15放入位置4,关键字38放入位置5,关键字61放入位置6,关键字84放入位置7,再添加关键字49,计算得到地址为5,冲突,用二次探测法解决冲突得到新地址为6,仍冲突,再用用二次探测法解决冲突,得到新地址为4,仍冲突,再用用二次探测法解决冲突,得到新地址为9,不冲突,即将关键字49放入位置9。
3.对于哈希函数H(Key) = key % 13, 被称为同义词的关键字是( D )。
A、35和41
B、23和39
C、15和44
D、25和51
习题解析:具有相同函数值的关键字对该哈希函数来说称作同义词,即key1不等于key2,而f(key1) = f(key2)。25和51对13取余得到相同的余数12。
4.从空树开始,依次插入结点23,12,8,34,28,78构造二叉平衡排序树,则构造好的二叉树按层序遍历的结果是(C)。
A、12,8,28,23,34,78
B、23,12,28,34,8,78
C、28,12,34,8,23,78
D、8,12,23,28,34,78

5.数据结构c语言版习题_第10张图片
1、28
2、43
3、8
4、37
5、18
6、47
7、75
8、26
9、62
10、1.444
习题解析:链地址法解决冲突,是将所有关键字为同义词的记录存储在同一线性链表中。
6数据结构c语言版习题_第11张图片
1、12
2、7
3、17
4、2
5、11
6、16
7、21
8、1
9、9
10、23
习题解析:二叉排序树中左子树的值均比根结点小,右子树的值均比根结点大,且每一颗子树均是二叉排序树。
7.数据结构c语言版习题_第12张图片
1、12
2、1
3、49
4、1
5、38
6、2
7、1
8、21
9、2
10、1.375
8.下列算法的功能为:采用折半方法进行关键字的查找,请将算法中缺失的语句按照顺序填入对应的空格。(注意:答案中不要出现空格)
结构定义:

typedef int KeyType;
typedef struct{      
   KeyType key;  
}ElemType;
typedef struct {
    ElemType *elem;   
   int length;       
} SSTable;
折半查找算法:
int Search_Bin(SSTable &ST,KeyType key){
//在有序表ST中折半查找其关键字等于key的数据元素
//若找到,则函数值为该元素在表中的位置,否则为0
int low=1, high=ST.length,mid;  
while(low<=high){

          
mid=(low+high)/2 ; // (1)

if(EQ(key,   ST.elem[mid].key ))    // (2)
   return mid;
    else if(LT(key,ST.elem[mid].key))             
high=mid-1  ; // (3)
         else     
  low=mid+1 ;  // (4)
}
return 0;   
}

你可能感兴趣的:(算法)