数据结构作业3重难点复习

一、判断题

1-1
对于顺序存储的长度为N的线性表,访问结点和增加结点的时间复杂度分别对应为O(1)和O(N)。

T
题目字眼 “ 顺序存储 ” ,说明内存单元中分配的存储空间是连续的,所
以该线性表为数组形式存储,所以数组访问时,通过下标可随机访问,时间复杂度为O(1),而增加插入时,需要涉及大量元素的移动,所以时间复杂度为O(N)。

1-2
若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用顺序表存储最节省时间。

T
存取任一指定序号”最好的方法是实现“随机存取”,则可采用顺序表。并且,因为插入和删除操作都是在最后进行的,所以无需大量移动数据元素,顺序表是最合适的。

1-3
对于顺序存储的长度为N的线性表,删除第一个元素和插入最后一个元素的时间复杂度分别对应为O(1)和O(N)。

F 顺序表对第一个元素和最后一个元素的操作,时间复杂度均为O(1)

在这里插入图片描述

顺序表是一种随机存储结构,所以逻辑相邻的元素在物理位置上也是相邻的

1-5
(neuDS)所谓随机存取,就是通过首地址和元素的位序号值可以在O(1)的时间内找到指定的元素。

T
随机存取就是直接存取,可以通过下标直接访问的那种数据结构,与存储位置无关,例如数组。
非随机存取就是顺序存取了,不能通过下标访问了,只能按照存储顺序存取,与存储位置有关,例如链表。

在这里插入图片描述
在这里插入图片描述

二、选择题

2-1
对于顺序存储的长度为N的线性表,访问结点和增加结点的时间复杂度为:B(1分)

A O(1), O(1)
B O(1), O(N)
C O(N), O(1)
D O(N), O(N)

2-2
在N个结点的顺序表中,算法的时间复杂度为O(1)的操作是:A(2分)

A 访问第i个结点(1≤i≤N)和求第i个结点的直接前驱(2≤i≤N)
B 在第i个结点后插入一个新结点(1≤i≤N)
C 删除第i个结点(1≤i≤N)
D 将N个结点从小到大排序

A.O(1) B.O(N)结点后移 C.O(N) 结点前移 D.最好为O(NlogN)最差为O(N^2)

2-3
若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用哪种存储方式最节省时间?D (2分)

A 双链表
B 单循环链表
C 带头结点的双循环链表
D 顺序表

2-4
顺序表中第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是(C)。(2分)

A 100
B 105
C 108
D 110

100+(5-1)*2

2-5
(neuDS)线性表的顺序存储结构是一种(A) (2分)

A 随机存取的存储结构
B 顺序存取的存储结构
C 索引存取的存储结构
D 散列存取的存储结构

大佬讲的很清楚

2-6
(neuDS)一个顺序表所占用的存储空间大小与©无关。 (2分)

A 表的长度
B 元素的类型
C 元素的存放顺序
D 元素中各字段的类型

2-7
(neuDS)要将一个顺序表{a​0,a1,……,an−1}中第i个数据元素​i(0≤i≤n-1)删除,需要移动(B)个数据元素。 (2分)

A i
B n-i-1
C n-i
D n-i+1

移动第i个数据之后的所有数据

2-8
用数组表示线性表的优点是(B)。 (2分)

A 便于插入和删除操作
B 便于随机存取
C 可以动态地分配存储空间
D 不需要占用一片相邻的存储空间

ACD均为链表的优点

2-9
若长度为n的线性表采用顺序存储结构,那么删除它的第i个数据元素之前,需要它一次向前移动(A)个数据元素。 (2分)

A n-i
B n+i
C n-i-1
D n-i+1

与2-7的不同是2-7题数据元素下标从0开始,但实际上也是移动了n-i个元素

2-10
若长度为n的线性表采用顺序结构,在第i个数据元素之前插入一个元素,需要它依次向后移动(B)个元素。 (2分)

A n-i
B n-i+1
C n-i-1
D i

2-11
线性表L=(a1, a2 ,……,an )用一维数组表示,假定删除线性表中任一元素的概率相同(都为1/n),则删除一个元素平均需要移动元素的个数是(C)。 (2分)

A n/2
B (n+1)/2
C (n-1)/2
D n

删除第一个元素移动0次,第二个移动1次。。。第n个移动n-1次,平均移动个数即(0+1+2+…+n-1)*(1/n)=(n-1)/2

三、函数题

6-1 顺序表创建和就地逆置 (10分)

本题要求实现顺序表的创建和就地逆置操作函数。L是一个顺序表,函数ListCreate_Sq(SqList &L)用于创建一个顺序表,函数ListReverse_Sq(SqList &L)是在不引入辅助数组的前提下将顺序表中的元素进行逆置,如原顺序表元素依次为1,2,3,4,则逆置后为4,3,2,1。

函数接口定义:

Status ListCreate_Sq(SqList &L);
void ListReverse_Sq(SqList &L);

裁判测试程序样例:


```c
//库函数头文件包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

//函数状态码定义
#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE -1
#define OVERFLOW   -2

typedef int  Status;

//顺序表的存储结构定义
#define LIST_INIT_SIZE  100
#define LISTINCREMENT   10
typedef int ElemType;  //假设线性表中的元素均为整型
typedef struct{
    ElemType* elem;   //存储空间基地址
    int length;       //表中元素的个数
    int listsize;     //表容量大小
}SqList;    //顺序表类型定义

Status ListCreate_Sq(SqList &L);
void ListReverse_Sq(SqList &L);

int main() {
    SqList L;
    ElemType *p;

    if(ListCreate_Sq(L)!= OK) {
        printf("ListCreate_Sq: 创建失败!!!\n");
        return -1;
    }

    ListReverse_Sq(L);

    if(L.length){
    for(p=L.elem;p<L.elem+L.length-1;++p){
        printf("%d ",*p);
    }
    printf("%d",*p); 
    }
    return 0;
}
/* 请在这里填写答案 */

输入格式: 第一行输入一个整数n,表示顺序表中元素个数,接下来n个整数为表元素,中间用空格隔开。 输出格式: 输出逆置后顺序表的各个元素,两个元素之间用空格隔开,最后一个元素后面没有空格。
输入样例:

4
1 2 3 4

输出样例:

4 3 2 1

答案:

//思路:创建链表时要检查表中元素个数的合法性,逆置表中元素时直接将第x个元素与倒数第x个元素做交换
//注意:表中元素的个数要合法,
Status ListCreate_Sq(SqList &L)
{
    
	int n;//数据表中元素的个数
	scanf("%d",&n);
	if(n<=0) return ERROR;//检测合法性 
	else
	{
		L.elem=(ElemType*)malloc(sizeof(ElemType)*n );
    if(!L.elem) exit(OVERFLOW);
     L.listsize=LIST_INIT_SIZE;
    L.length=0;
	int i; 
	for(i=0;i<n;i++)
	{
	     scanf("%d",&L.elem[i]);	
	}
	L.length=n;
    return OK;
    }
}

void ListReverse_Sq(SqList &L)
{
	int i;
	 for(i=0;i<L.length/2;i++)
	{
	  int t=*(L.elem+i);//第x个元素与倒数第x个元素做交换 
	 *(L.elem+i)=*(L.elem+L.length-i-1);
	 *(L.elem+L.length-i-1)=t;
     }
}

6-2 有序顺序表的插入 (10分)

本题要求实现递增顺序表的有序插入函数。L是一个递增的有序顺序表,函数Status ListInsert_SortedSq(SqList &L, ElemType e)用于向顺序表中按递增的顺序插入一个数据。 比如:原数据有:2 5,要插入一个元素3,那么插入后顺序表为2 3 5。 要考虑扩容的问题。
函数接口定义:

Status ListInsert_SortedSq(SqList &L, ElemType e);

裁判测试程序样例:

//库函数头文件包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

//函数状态码定义
#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE -1
#define OVERFLOW   -2

typedef int  Status;

//顺序表的存储结构定义
#define LIST_INIT_SIZE  100
#define LISTINCREMENT   10
typedef int ElemType;  //假设线性表中的元素均为整型
typedef struct{
    ElemType* elem;   //存储空间基地址
    int length;       //表中元素的个数
    int listsize;     //表容量大小
}SqList;    //顺序表类型定义

//函数声明
Status ListInsert_SortedSq(SqList &L, ElemType e);

//顺序表初始化函数
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;
}

//顺序表输出函数
void ListPrint_Sq(SqList L)
{
    ElemType *p = L.elem;//遍历元素用的指针


    for(int i = 0; i < L.length; ++i){
        if(i == L.length - 1){
            printf("%d", *(p+i));
        }
        else{
            printf("%d ", *(p+i));
        }
    }
}
int main()
{
    //声明一个顺序表
    SqList L;
    //初始化顺序表
    InitList_Sq(L);

    int number = 0;
    ElemType e;

     scanf("%d", &number);//插入数据的个数 

    for(int i = 0; i < number; ++i)
    {
    scanf("%d", &e);//输入数据
        ListInsert_SortedSq(L, e);
    }

    ListPrint_Sq(L);

    return  0;
}


/* 请在这里填写答案 */

输入格式: 第一行输入接下来要插入的数字的个数 第二行输入数字 输出格式: 输出插入之后的数字
输入样例:

5
2 3 9 8 4

输出样例:

2 3 4 8 9

答案:

//思路:从表中最后一个数据开始遍历,如果他比插入的的数据大,则其向后移一位,否则结束循环,循环结束的位置即为插入元素的位置
//注意:表长等于表容时,要扩容;插入元素后表长要加一
Status ListInsert_SortedSq(SqList &L, ElemType e)
{
	if (L.listsize == L.length)
	{
	    L.elem=(ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));//表满扩容
		if (!L.elem)exit(OVERFLOW);
		L.listsize += LISTINCREMENT;
   }
	int i;
	for(i=L.length;i>0;i--)//从表中最后一个数据开始遍历
	{
		ElemType *p=(L.elem+i-1);
        if(*p>e) //如果他比插入的的数据大,则其向后移一位
		{
			*(p+1)=*p;
		} 	
		 else break;//否则结束循环
    }
    *(L.elem+i)=e;//循环结束的位置即为插入元素的位置
	L.length++;//插入元素后表长要加一
	return 1;
}

7-1 数组循环左移 (20分)

本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置,即将a中的数据由(a​0​​ a​1​​ ⋯a​n−1)变换为(a​m⋯a​n−1a​0a​1​​ ⋯a​m−1 )(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:
输入第1行给出正整数n(≤100)和整数m(≥0);第2行给出n个整数,其间以空格分隔。

输出格式:
在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

输入样例:

8 3
1 2 3 4 5 6 7 8

输出样例:

4 5 6 7 8 1 2 3
//思路:创建链表后,先将整个链表逆置,然后将前一部分元素逆置,再将后一部分元素逆置,最后顺序输出
//注意:判断有效范围,左移的位置比元素总个数大时,需要取余提高效率
//库函数头文件包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

//函数状态码定义
#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE -1
#define OVERFLOW   -2

typedef int  Status;

//顺序表的存储结构定义
#define LIST_INIT_SIZE  100
#define LISTINCREMENT   10
typedef int ElemType;  //假设线性表中的元素均为整型
typedef struct{
    ElemType* elem;   //存储空间基地址
    int length;       //表中元素的个数
    int listsize;     //表容量大小
}SqList;    //顺序表类型定义

Status ListCreate_Sq(SqList &L,int n);
void ListReverse_Sq1(SqList &L,int c,int d); 
void ListReverse_Sq2(SqList &L,int c,int d);
void print(SqList &L);
int main() {
   SqList L;
    int n;//数据表中元素的个数
	scanf("%d",&n);
	int m;scanf("%d",&m);
	if(n>100||n<0||m<0) printf("ERROR");
	else
	{ 
      if(ListCreate_Sq(L,n)!= OK) {
        printf("ListCreate_Sq: 创建失败!!!\n");
        return -1;
      }

//    ListReverse_Sq1(L,0,n-1);//逆置所有元素 
//    print(L);
//    ListReverse_Sq1(L,0,n-m-1);// 逆置前面的元素
//	print(L); 
//    ListReverse_Sq1(L,n-m,n-1);//逆置剩下的元素
//	print(L); 
    ListReverse_Sq2(L,0,m);//逆置前m个元素 
    print(L);
    ListReverse_Sq2(L,m,m+n);//逆置后n-m个元素 
    print(L);
    ListReverse_Sq2(L,0,n);//所有元素逆置 
    print(L);
   }
   //print(L);
    return 0;
}

Status ListCreate_Sq(SqList &L,int n)
{
	if(n<=0) return ERROR;//检测合法性 
	else
	{
		L.elem=(ElemType*)malloc(sizeof(ElemType)*n );
    if(!L.elem) exit(OVERFLOW);
     L.listsize=LIST_INIT_SIZE;
    L.length=0;
	int i; 
	for(i=0;i<n;i++)
	{
	     scanf("%d",&L.elem[i]);	
	}
	L.length=n;return OK;
    }
   
}
void print(SqList &L)
{
	ElemType *p;
	if(L.length){
	for(p=L.elem;p<L.elem+L.length-1;p++)
	{
	    printf("%d ",*p);
	}
	printf("%d",*p); 
    }
    printf("\n");
}

//链表逆置 
void ListReverse_Sq1(SqList &L,int c,int d)//这里c表示起始下标,d表示终止下标
{
	int i,j,k;
	k=(d-c-1)/2;//计算交换次数
	 for(i=0;i<=k;i++)
	{
	  int t=*(L.elem+c);//第x个元素与倒数第x个元素做交换 注意第一个元素的位置 
	 *(L.elem+c)=*(L.elem+d);
	 *(L.elem+d)=t;
	 c++;d--;//依次交换 
     }
}
void ListReverse_Sq2(SqList &L,int c,int d)//这里c表示起始位置,d-c表示终止位置 
{
	 int i,t;
	for(i=c;i<d/2;i++)
	{
	   	t=L.elem[i];
	   	L.elem[i]=L.elem[d-i-1];
	   	L.elem[d-i-1]=t;
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值