第二章作业题2-链表(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fighting123678/article/details/82714678

一、判断题

1、这里写图片描述
访问结点的时间复杂度为O(N)

2、这里写图片描述

3、这里写图片描述

 将长度为n的单链表链接在长度为m的单链表之后的算法的时间复杂度为
将长度为n的单链表链接在长度为m的单链表之后的算法的时间复杂度为( )
A.O(1) B.O(n) C.O(m) D.O(m+n) 

解释:
要插入到长度为m的单链表,需要找到表尾,这个过程的时间复杂度为o(m),连接的时间复杂度为0(1),所以总的时间复杂度为0(m) 

因此如果仅仅是合并的话,时间复杂度为O(1)

4、这里写图片描述


二、选择题
1、这里写图片描述
解释:t的下一个为h,然后h重新再指向t,这样h一直都是指向首元结点

2、这里写图片描述

3、这里写图片描述

4、这里写图片描述

5、这里写图片描述

在一个具有n个节点的单链表中:
(1)在地址为…的结点之前/之后、插入/删除某一个结点的话,时间复杂度为O(1);
(2)在第 i 个结点之前/之后、插入/删除一个新结点,或者,删除第 i 个结点,时间复杂度为O(n);
(3)在一个具有n个结点的有序单链表中插入一个新结点并仍然保持有序的时间复杂度是O(n);

在n个结点的*顺序表*中,算法的时间复杂度是O(1)的操作是:
A.访问第i个结点和求第i个结点的直接前驱
B.在第i个结点后插入一个新结点
C.删除第i个结点
D.将n个结点从小到大排序




答案是A.
假设顺序表L,长度为n,求第i个节点L[i],直接前驱L[i-1],因此为O(1)
答案B需要移动n-i个节点,因此为O(n)
答案C也需要移动n-i个节点
答案D根据排序方法不同最慢O(n^2),最快O(nlogn)

一定要看清是顺序表还是链表,看清所给的条件,然后再进行判断

6、这里写图片描述
要找到那个点的话,需要从头开始找,最坏的情况是在最后一个

7、这里写图片描述

8、这里写图片描述

因为,从头按照顺序遍历一遍肯定能插入,时间复杂度为O(n);

9、这里写图片描述

10、这里写图片描述

11、这里写图片描述

12、这里写图片描述

13、这里写图片描述

14、这里写图片描述


三、函数题

1、带头结点的单链表就地逆置 (10 分)

本题要求编写函数实现带头结点的单链线性表的就地逆置操作函数。L是一个带头结点的单链表,函数ListReverse_L(LinkList &L)要求在不新开辟节点的前提下将单链表中的元素进行逆置,如原单链表元素依次为1,2,3,4,则逆置后为4,3,2,1。
函数接口定义:

void ListReverse_L(LinkList &L);

其中 L 是一个带头结点的单链表。
裁判测试程序样例:

//库函数头文件包含
#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;
typedef int  ElemType; //假设线性表中的元素均为整型

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;

Status ListCreate_L(LinkList &L,int n)
{
    LNode *rearPtr,*curPtr;   //一个尾指针,一个指向新节点的指针
    L=(LNode*)malloc(sizeof (LNode));
    if(!L)exit(OVERFLOW);
    L->next=NULL;               //先建立一个带头结点的单链表
    rearPtr=L;  //初始时头结点为尾节点,rearPtr指向尾巴节点
    for (int i=1;i<=n;i++){  //每次循环都开辟一个新节点,并把新节点拼到尾节点后
        curPtr=(LNode*)malloc(sizeof(LNode));//生成新结点
        if(!curPtr)exit(OVERFLOW);
        scanf("%d",&curPtr->data);//输入元素值
        curPtr->next=NULL;  //最后一个节点的next赋空
        rearPtr->next=curPtr;
        rearPtr=curPtr;
    }
    return OK;
}
void ListReverse_L(LinkList &L);
void ListPrint_L(LinkList &L){
//输出单链表
    LNode *p=L->next;  //p指向第一个元素结点
    while(p!=NULL)
    {
          if(p->next!=NULL)
               printf("%d ",p->data);
          else
               printf("%d",p->data);
          p=p->next;
    }
}
int main()
{
    LinkList L;
    int n;
    scanf("%d",&n);
    if(ListCreate_L(L,n)!= OK) {
          printf("表创建失败!!!\n");
          return -1;
    }
    ListReverse_L(L);
    ListPrint_L(L);
    return 0;
}
/* 请在这里填写答案 */

输入格式:

第一行输入一个整数n,表示单链表中元素个数,接下来一行共n个整数,中间用空格隔开。

输出格式:

输出逆置后顺序表的各个元素,两个元素之间用空格隔开,最后一个元素后面没有空格。
输入样例:

4
1 2 3 4

输出样例:

4 3 2 1

答案:
原地逆置的时候,刚开始本来是想从最后一个开始一个个向前方,但是根据链表的特性,不太好操作,因此,想到第一个位置紧邻的是第二个,第二个位置紧邻的是第三个,第三个位置紧邻的是第四个,依次类推,这要这条线不断,就可以不断找到下一个,然后依次将第二个拿到第一个的前面,第三个拿到第二个的前面,第四个拿到第三个的前面。

实现这个的重点是保证这条线不断,同时又能有一个可以独立出来。因此可以得到如图所示的过程

这里写图片描述

void ListReverse_L(LinkList &L)
{
    LinkList p,r;
    p=L->next;//这样p就是L的下一个,即使L变了,p指向的下一个还是不变;
    L->next=NULL;//这就意味着,必须要从头开始一个个元素重新插入;
    while(p)
    {
        r=p;//p一直向下移动,r则负责插入;
        p=p->next;//这一句必须在这个位置,不能在下面;
        //因为p和r指向同一个位置,对于所指的下一个地址是一样的;
        //因此,之后对于r的操作,等同于对于p的操作,所以p所指的位置会变;
        //所以,必须要在这让p指向下一个位置,以便于把r单独分开;
        r->next=L->next;
        L->next=r;
        //p=p->next;
    }
}

这里可能会以为L指向的变了,那样q指向的下一个就不是L中本身应该指向的顺序,其实这样的理解是错误的,这是链表,不管L怎么变,q指向的都不会变。仍然会沿着这条线。


四、编程题

1、jmu-ds-单链表的基本运算

实现单链表的基本运算:初始化、插入、删除、求表的长度、判空、释放。
(1)初始化单链表L,输出L->next的值;
(2)依次采用尾插法插入元素:输入分两行数据,第一行是尾插法需要插入的字符数据的个数,第二行是具体插入的字符数据。
(3)输出单链表L;
(4)输出单链表L的长度;
(5)判断单链表L是否为空;
(6)输出单链表L的第3个元素;
(7)输出元素a的位置;
(8)在第4个元素位置上插入‘x’元素;
(9)输出单链表L;
(10)删除L的第3个元素;
(11)输出单链表L;
(12)释放单链表L。
输入格式:

两行数据,第一行是尾插法需要插入的字符数据的个数,第二行是具体插入的字符数据。
输出格式:

按照题目要求输出
输入样例:

5
a b c d e
输出样例:

0
a b c d e
5
no
c
1
a b c x d e
a b x d e

答案:

#include <bits/stdc++.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2

typedef int Status;
typedef char ElemType;

typedef struct LNode
{
    ElemType data;
    struct LNode* next;
} LNode,*LinkList;

//初始化单链表
Status InitList(LinkList &L)//这里有&号
{
    L=(LinkList)malloc(sizeof(LNode));
    if(!L) exit(OVERFLOW);
    L->next=NULL;
    return OK;
}

//输入(尾部插入)链表
Status InsertList(LinkList &L,int n)
{
    LinkList p,r;
    p=L;//等于的是L,因为是从开头插入,要先找到前一个元素;
    for(int i=0; i<n; i++)
    {
        r=(LinkList)malloc(sizeof(LNode));
        if(!r) exit(OVERFLOW);
        scanf(" %c",&r->data);//这里注意读取的方式;
        r->next=NULL;
        p->next=r;
        p=r;
    }
    return OK;
}

//输出链表
void PrintfLinkList(LinkList L)
{
    LinkList p;
    p=L->next;
    while(p)
    {
        if(p==L->next)  printf("%c",p->data);
        else printf(" %c",p->data);
        p=p->next;//这一句千万别忘了啊!!!!!;
    }
    printf("\n");
}

//判断链表是否为空
Status EmptyLinkList(LinkList L)
{
    if(L->next==NULL)  return TRUE;
    else return FALSE;
}

//输出单链表L的第n个元素
Status ElemLink(LinkList L,int i)
{
    LinkList p;
    p=L->next;
    int j=1;
    while(p&&j<i)
    {
        p=p->next;
        j++;
    }
    if(!p||j>i)  exit(OVERFLOW);
    printf("%c\n",p->data);
    return OK;
}

//输出某一个元素的位置
Status LocateLink(LinkList L,ElemType e)
{
    LinkList p;
    p=L->next;
    int j=1;
    while(p)
    {
        if(p->data==e)
        {
            printf("%d\n",j);
            return OK;
        }
        else
        {
            p=p->next;
            j++;
        }
    }
    return ERROR;
}

//在某一个位置上插入元素
Status InsertList_L(LinkList &L,int i,ElemType e)
{
    LinkList p,r;
    p=L;
    int j=0;
    while(p&&j<i-1)
    {
        p=p->next;
        j++;
    }
    if(!p||j>i-1) exit(OVERFLOW);
    r=(LinkList)malloc(sizeof(LNode));
    r->data=e;//千万别忘记输入元素;
    r->next=p->next;
    p->next=r;
    return OK;
}

//删除L的第n个元素
Status DeleteList(LinkList &L,int i)
{
    LinkList p,r;
    p=L;
    int j=0;
    while(p->next&&j<i-1)
    {
        p=p->next;
        j++;
    }
    if(!(p->next)||j>i-1) exit(OVERFLOW);
    r=p->next;
    p->next=r->next;
    free(r);
}

int main()
{
    LinkList L;
    InitList(L);

    int n;
    scanf("%d",&n);
    printf("%d\n",L->next);
    InsertList(L,n);

    PrintfLinkList(L);
    printf("%d\n",n);

    if(EmptyLinkList(L)==TRUE)  printf("yes\n");
    else  printf("no\n");

    ElemLink(L,3);

    LocateLink(L,'a');

    InsertList_L(L,4,'x');
    n++;//这里别忘了;
    PrintfLinkList(L);

    DeleteList(L,3);
    PrintfLinkList(L);
    free(L);
}

注意:
(1)对于scanf,scanf只有在遇到\n,也就是是回车时才结束输入,但是遇到空格和tab时就会停止读取。

用scanf不是不显示空格,而是用scanf接收字符串的话,在串首遇到空格的话,跳过,继续寻找下一个非空格字符,在串中遇到空格时,结束字符串的输入。所以如果用户输入" abcd efg"的话,scanf取得的字符串为"abcd"。

scanf(" %c",&r->data);这样的话可以忽略空格键,如果%c前面没有空格的话,输入会停止。

(2)记住scanf的用法,如果只想输入某一个字符,而忽略空格的话,就要采用scanf(" %c",&r->data);的样式,即使是前面有两个空格,这样也对,即使是空格在后面,这样也对。


2、 两个有序链表序列的合并 (20 分)

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。
输入格式:

输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:

在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。
输入样例:

1 3 5 -1
2 4 6 8 10 -1

输出样例:

1 2 3 4 5 6 8 10

答案

//库函数头文件包含
#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;
typedef int  ElemType; //假设线性表中的元素均为整型

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} LNode,*LinkList;
//初始化链表
Status CreatLink(LinkList &L)
{
    L=(LinkList)malloc(sizeof(LNode));
    if(!L) exit(OVERFLOW);
    L->next=NULL;
    LinkList p,r;
    p=L;
    int n;
    scanf("%d",&n);
    while(n!=-1)
    {
        r=(LinkList)malloc(sizeof(LNode));
        if(!r) exit(OVERFLOW);
        r->data=n;
        r->next=NULL;
        p->next=r;
        p=r;
        scanf("%d",&n);
    }
    return OK;
}

//输出链表
void PrintfLinkList(LinkList L)
{
    LinkList p;
    p=L->next;
    if(p==NULL) printf("NULL\n");
    else
    {
        while(p)
        {
            if(p==L->next)  printf("%d",p->data);
            else printf(" %d",p->data);
            p=p->next;//这一句千万别忘了啊!!!!!;
        }
        printf("\n");
    }
}

void BingLink(LinkList &LA,LinkList &LB,LinkList& LC)
{
    LC=(LinkList)malloc(sizeof(LNode));//千万不要忘记给LC分配空间;
    if(!LC) exit(OVERFLOW);
    LC->next=NULL;
    LinkList pa,pb,pc;
    pa=LA->next;
    pb=LB->next;
    LC=LA;
    pc=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;
        }
    }
    pc->next=pa?pa:pb;//插入剩余段;
    free(LB);//释放LB头结点
}
int main()
{
    LinkList LA,LB;
    CreatLink(LA);
    CreatLink(LB);
    LinkList LC;
    BingLink(LA,LB,LC);

    PrintfLinkList(LC);
    return 0;
}

3、两个有序链表序列的交集

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2的交集新链表S3。
输入格式:

输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:

在一行中输出两个输入序列的交集序列,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。
输入样例:

1 2 5 -1
2 4 5 8 10 -1

输出样例:

2 5

答案

//库函数头文件包含
#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;
typedef int  ElemType; //假设线性表中的元素均为整型

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} LNode,*LinkList;
//初始化链表
Status CreatLink(LinkList &L)
{
    L=(LinkList)malloc(sizeof(LNode));
    if(!L) exit(OVERFLOW);
    L->next=NULL;
    LinkList p,r;
    p=L;
    int n;
    scanf("%d",&n);
    while(n!=-1)
    {
        r=(LinkList)malloc(sizeof(LNode));
        if(!r) exit(OVERFLOW);
        r->data=n;
        r->next=NULL;
        p->next=r;
        p=r;
        scanf("%d",&n);
    }
    return OK;
}

//输出链表
void PrintfLinkList(LinkList L)
{
    LinkList p;
    p=L->next;
    if(p==NULL) printf("NULL\n");
    else
    {
        while(p)
        {
            if(p==L->next)  printf("%d",p->data);
            else printf(" %d",p->data);
            p=p->next;//这一句千万别忘了啊!!!!!;
        }
        printf("\n");
    }
}

void BingLink(LinkList &LA,LinkList &LB,LinkList& LC)
{
    LC=(LinkList)malloc(sizeof(LNode));//千万不要忘记给LC分配空间;
    if(!LC) exit(OVERFLOW);
    LC->next=NULL;
    LinkList pa,pb,pc;
    pa=LA->next;
    pb=LB->next;
    pc=LC;
    pc=LC;
    while(pa&&pb)
    {
        if((pa->data)==(pb->data))
        {
            pc->next=pa;
            pa=pa->next;
            pb=pb->next;
            pc=pc->next;
        }
        else if((pa->data)<(pb->data))
        {
            pa=pa->next;
        }
        else
            pb=pb->next;
    }
}
int main()
{
    LinkList LA,LB;
    CreatLink(LA);
    CreatLink(LB);
    LinkList LC;
    BingLink(LA,LB,LC);

    PrintfLinkList(LC);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fighting123678/article/details/82714678