线性表练习

( 1)顺 序表中 第一个 元 素的存储 地址 是 100 ,每 个元素的 长度 为 2,则 第 5 个 元 素 的 地 址 是 ( )。 A. 110 B . 108 C. 100 D. 120
答案: B
解释:顺序表中的数据连续存储,所以第 5 个元素的地址为: 100+2*4=108 。

 

**( 2)在 n 个结点的顺序表中,算法的时间复杂度是 O(1) 的操作是() 。 A .访问第 i 个结点( 1≤ i≤ n)和求第 i 个结点的直接前驱( 2≤ i≤ n) B .在第 i 个结点后插入一个新结点( 1≤ i≤ n) C.删除第 i 个结点( 1≤ i≤ n) D .将 n 个结点从小到大排序
答案: A
解释: 在顺序表中插入一个结点的时间复杂度都是 O(n 2) ,排序的时间复杂度为 O(n 2 ) 或 O(nlog 2n)。顺序表是一种随机存取结构,访问第 i 个结点和求第 i 个结点的直接前驱都可以直接通过数组的下标直接定位,时间复杂度是 O(1) 。


( 3)向一个有 127 个元素的顺序表中插入一个新元素并保持原来顺序不变, 平均要移动的元素个数为() 。 A. 8 B . 63.5 C . 63 D. 7

答案: B
解释:平均要移动的元素个数为: n/2 。

 

( 4)单链表的存储密度() 。
A .大于 1 B .等于 1 C.小于 1 D.不能确定
答案: C
解释:存储密度是指一个结点数据本身所占的存储空间和整个结点所占的存储空
间之比,假设单链表一个结点本身所占的空间为 D,指针域所占的空间为 N,则存储密度为: D/(D+N) ,一定小于 1。

(5) 创建一个包括 n 个结点的有序单链表的时间复杂度是() 。 A . O(1) B . O(n) C. O(n 2) D . O(nlog 2n)
答案: C
解释:单链表创建的时间复杂度是 O(n) ,而要建立一个有序的单链表,则每生成一个新结点时需要和已有的结点进行比较,确定合适的插入位置,所以时间复杂度是O(n2) 。

 

算法设计题:

( 1)将两个递增的有序链表合并为一个递增的有序链表。 要求结果链表仍使用原来两个链表的存储空间 , 不另外占用其它的存储空间。表中不允许有重复的数据。

题解:从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,依次摘取其中较小者重新链接在Lc表的最后。如果两个表中的元素相等,只摘取La表中的元素,删除Lb表中的元素,这样确保合并后表中无重复的元素。当一个表到达表尾结点,为空时,将非空表的剩余元素直接链接在Lc表的最后。

复制代码
#include <stdio.h>
#include<stdlib.h>
 
typedef struct LNode
{
    int data;
    LNode *next;
}LNode,*LinkList;//*代表LinkList是指针类型,用该类型定义的指针指向LNode
 
//尾插法创建链表
int CreateList(LinkList &L,int n)
{
    LNode *p,*r;int i;
    L=new LNode;//创建头结点
    L->next=NULL;//头结点置空
    r=L;//尾指针指向L
    for(i=0;i<n;i++)
    {
        p=new LNode;
        scanf("%d",&p->data);
        p->next=NULL;r->next=p;
        r=p;
    }
    return 0;
}
 
 
 
//输出链表
void print(LinkList L)
{
    LinkList p;
    p=L->next;
    while(p)
    {
      printf("%d ",p->data);
      p=p->next;
    }
}
 
//合并
void MergeList_L(LinkList &LA,LinkList &LB,LinkList &LC)
{
 
    LNode *pa;LNode *pb;LNode *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 if(pa->data>pb->data)
        {
            pc->next=pb;
            pc=pb;
            pb=pb->next;
        }
        else
        {
            pc->next=pa;
            pc=pa;
            pa=pa->next;
            pb=pb->next;
        }
    }
    pc->next=pa?pa:pb;
    delete LB;
}
 
int main()
{
    LinkList LA;LinkList LB;LinkList LC;int n;
    printf("请输入需要创建的LA链表的长度:\n");
    scanf("%d",&n);
    printf("请依次输入需要存入的数据(尾插法且递增):\n");
    CreateList (LA,n);
 
 
    printf("请输入需要创建的LB链表的长度:\n");
    scanf("%d",&n);
    printf("请依次输入需要存入的数据(尾插法且递增):\n");
    CreateList (LB,n);
 
    printf("当前LA链表为:\n");
    print(LA);
    printf("\n");
    printf("当前LB链表为:\n");
    print(LB);
    printf("\n");
 
    MergeList_L(LA,LB,LC);
    printf("合并后的LC链表为:\n");
 
    print(LC);
    return 0;
}
复制代码

(2)已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出 A 与 B 的交集,并存放于 A 链表中。

题解:

从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,如果两个表中相等的元素时,摘取La表中的元素,删除Lb表中的元素;如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移。当链表La和Lb有一个到达表尾结点,为空时,依次删除另一个非空表中的所有元素。

复制代码
#include <stdio.h>
#include<stdlib.h>
 
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode, *LinkList;
 
int InitList(LinkList &L)
{
    L = new LNode;
    L->next = NULL;
    return 1;
}
 
void TraveList(LinkList L)
{
    LNode *p;
    p = L->next;
 
    while (p)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}
 
// 尾插法建立链表
void CreateList(LinkList &L, int n)
{
    L = new LNode;
    L->next = NULL;
    LNode *r;
    r = L;
    for (int i = 0; i < n; i++)
    {
        printf("请输入链表第%d个元素的值:", i + 1);
        LNode *s;
        s = new LNode;
        scanf("%d", &s->data);
        s->next = NULL;
        r->next = s;
        r = s;
    }
}
 
// 链表交集
void Intersection(LinkList &L1, LinkList &L2, LinkList &L3)
{
    LNode *p1, *p2, *p3, *q, *u;
    p1 = L1->next;
    p2 = L2->next;  // p1和p2分别是链表L1和L2的工作指针,初始化为相应链表的第一个结点
    p3 = L3 = L1;   // 用L1的头结点作为L3的头结点
    
    while (p1&&p2)
    {
        if (p1->data == p2->data)    //交集并入结果表中。
        { 
            p3->next = p1; 
            p3 = p1; 
            p1 = p1->next;
            u = p2; 
            p2 = p2->next; 
            delete u; 
        }
        else if (p1->data < p2->data) 
        { 
            u = p1; 
            p1 = p1->next; 
            delete u; 
        }
        else 
        { 
            u = p2; 
            p2 = p2->next; 
            delete u; 
        }
    }
    while (p1) // 释放结点空间
    { 
        u = p1;
        p1 = p1->next; 
        delete u; 
    }
    
    while (p2)   // 释放结点空间
    {
        u = p2; 
        p2 = p2->next; 
        delete u;
    }
    
    p3->next = NULL;    // 置链表尾标记。
    
    delete L2;    // 释放Lb的头结点
}
 
int main()
{
    LinkList L1, L2, L3;
 
    if (InitList(L1))
    {
        printf("L1初始化成功!\n");
    }
    else
    {
        printf("L1初始化失败!\n");
    }
 
    if (InitList(L2))
    {
        printf("L2初始化成功!\n");
    }
    else
    {
        printf("L2初始化失败!\n");
    }
 
    if (InitList(L3))
    {
        printf("L3初始化成功!\n");
    }
    else
    {
        printf("L3初始化失败!\n");
    }
 
    printf("请输入L1的长度:");
    int n1;
    scanf("%d", &n1);
    CreateList(L1, n1);
    TraveList(L1);
 
    printf("请输入L2的长度:");
    int n2;
    scanf("%d", &n2);
    CreateList(L2, n2);
    TraveList(L2);
 
    Intersection(L1, L2, L3);
    printf("链表交集:\n");
    TraveList(L3);
 
    return 0;
}
复制代码

(3)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。

复制代码
#include<stdio.h>
#include<stdlib.h>

typedef int Status;
typedef int Elemtype;
#define OK 1
#define ERROR 0 
typedef struct LNode
{
    Elemtype data;
    struct LNode *next;
}LNode,*LinkList;
 
void CreateList_L(LinkList &L,int n)  //尾插法建立
{   int i;
    LNode *r,*p;
    L=new LNode;
    L->next=NULL;
    r=L;
    printf("请输入元素:\n");
    for(i=0;i<n;++i)
    {
        p=new LNode;
        scanf("%d",&p->data);
        p->next=NULL;
        r->next=p;
        r=p;
    }
}

void MaxElem_L(LinkList &L)
{
    int max,i=0;
    LNode *p=L->next;
    max=p->data;
    while(p)
    {
        if(p->data>max)
           max=p->data;
        p=p->next;
    }
    p=L->next;
    while(p)
    {   i++;
        if(p->data==max)
           printf("第%d个结点的值为:%d\n",i,p->data); 
        p=p->next;
    }
    
}
int main()
{   int n;
    LNode *L;
    
    printf("请输入线性表的元素个数:");
    scanf("%d",&n);
    CreateList_L(L,n);
    printf("链表中值最大的结点是:\n");
    MaxElem_L(L);
    return 0; 
}
复制代码

(4)设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的

复制代码
#include<stdio.h>
#include<stdlib.h>

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

//创建单链表 尾插法
void CreateList(LinkList &L,int n)
{
    LNode *r,*p;
    L = new LNode;
    L->next = NULL;
    r = L;
    printf("输入链表元素\n");
    for(int i=0;i<n;i++)
    {
        p = new LNode;
        scanf("%d",&p->data);
        p->next = NULL;
        r->next = p;
        r = p;
    }
}

//逆转(利用前插法)
void Inverse(LinkList &L)
{
    LinkList p,q;
    p = L->next;
    L->next = NULL;
    //前插法
    while(p != NULL)
    {
        q = p->next;
        p->next = L->next;
        L->next = p;
        p = q;
    }
}

void Display(LinkList &L)
{
    LNode *p;
    p = L->next;

    while(p != NULL)
    {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
}

int main()
{
    int n;
    LinkList L;
    printf("请输入单链表的长度:\n");
    scanf("%d",&n);

    CreateList(L,n);

    printf("逆转后的单链表为:\n");
    Inverse(L);
    Display(L);

    return 0;
}
复制代码

(5)已知长度为 n 的线性表 A 采用顺序存储结构,请写一时间复杂度为 O(n) 、空间复

杂度为 O(1) 的算法,该算法删除线性表中所有值为 item 的数据元素。

 

复制代码
#include<stdio.h>
#include<stdlib.h>
typedef struct DLnode 
{
    int data;
    struct DLnode *prior;
    struct DLnode *next;
}DLnode, *LinkList;
 
int InitList(LinkList &L) 
{
    L = new DLnode;
    L->next = L;
    L->prior = L;
    return 1;
}
 
void TraveList(LinkList L) 
{
    DLnode *p;
    p = L->next;
    
    while (p != L) 
    {
        printf("%d ", p->data);
        p = p->next;
    }
    
    printf("\n");
}
 
int ListLength(LinkList &L) 
{
    DLnode *p;
    p = L->next;
    int length = 0;
    while (p!=L) 
    {
        length++;
        p = p->next;
    }
    
    return length;
}
 
void CreateList(LinkList &L, int &n)   //尾插法创造
{
    L = new DLnode;
    L->next = L;
    L->prior = L;
    DLnode *p;
    p = L;
    
    for (int i = 0; i < n; i++) 
    {
        printf("请输入第%d个元素的值:", i + 1);
        DLnode *s;
        s = new DLnode;
        scanf("%d", &s->data);
        p->next = s;
        s->next = L;
        s->prior = p;
        p = s;
    }
}
 
void Change(LinkList p)   //核心算法
{
    DLnode *q;
    q = p->prior;
    
    q->prior->next = p;          // p的前驱的前驱之后继为p
    p->prior = q->prior;    // p的前驱指向其前驱的前驱。
    
    q->next = p->next;    // p的前驱的后继为p的后继。 
    p->next->prior = q;   // p的后继的前驱指向原p的前驱
    
    q->prior = p;     // p与其前驱交换
    p->next = q;    // p的后继指向其原来的前驱
}
 
int main() 
{
    LinkList L;
    
    if (InitList(L)) 
    {
        printf("L初始化成功\n");
    }
    else 
    {
        printf("L初始化失败.\n");
    }
 
    printf("请输入链表元素个数:");
    int n;
    scanf("%d", &n);
    CreateList(L, n);
    TraveList(L);
    printf("链表长度:%d\n", ListLength(L));
    
    printf("请输入要交换的结点的值:");
    DLnode *s;
    s = new DLnode;
    scanf("%d", &s->data);
    DLnode *p;
    p = L->next;
    while (p != L) 
    {
        if (p->data == s->data)     //寻找节点
        {
            Change(p);
 
            break;
        }
        else 
        {
            p = p->next;
        }
    }
    
    TraveList(L);
 
    return 0;
}
复制代码

 

 

 

 

 

 
posted @   七月猫合  阅读(571)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示