数据结构 实验二 单链表实验 实验报告(合肥工业大学 2023级)

合肥工业大学 2023级 数据结构 实验二 完整报告

1.实验目标

  1. 熟练掌握线性表的链式存储结构。
  2. 熟练掌握单链表的有关算法设计和实现。
  3. 根据具体问题的需要,设计出合理的表示数据的链式存储结构,并设计相关算法。

2.实验要求

  1. 本次实验中的链表结构指带头结点的单链表;
  2. 单链表结构和运算定义,算法的实现以库文件方式实现,不得在测试主程序中直接实现;比如存储、算法实现放入文件:linkedList.h
  3. 程序运行、测试正确;
  4. 实验程序有较好可读性,各运算和变量的命名直观易懂,符合软件工程要求;
  5. 程序有适当的注释,程序的书写要采用缩进格式。

3.实验内容

编写算法实现下列问题的求解。

1.

将单链表L中的奇数项和偶数项结点分解开(元素值为奇数、偶数),分别放入新的单链表中,然后原表和新表元素同时输出到屏幕上,以便对照求解结果。

实验测试数据基本要求:

第一组数据:单链表元素为 (1,2,3,4,5,6,7,8,9,10,20,30,40,50,60)

第二组数据:单链表元素为 (10,20,30,40,50,60,70,80,90,100)

2.

求两个递增有序单链表L1和L2中的公共元素,放入新的单链表L3中。

实验测试数据基本要求:

第一组

第一个单链表元素为 (1,3,6,10,15,16,17,18,19,20)

第二个单链表元素为 (1,2,3,4,5,6,7,8,9,10,18,20,30)

第二组

第一个单链表元素为 (1,3,6,10,15,16,17,18,19,20)

第二个单链表元素为 (2,4,5,7,8,9,12,22)

第三组

第一个单链表元素为 ()

第二个单链表元素为 (1,2,3,4,5,6,7,8,9,10)

3.

删除递增有序单链表中的重复元素,要求时间性能最好。

实验测试数据基本要求:

第一组数据:单链表元素为 (1,2,3,4,5,6,7,8,9)

第二组数据:单链表元素为 (1,1,2,2,2,3,4,5,5,5,6,6,7,7,8,8,9)

第三组数据:单链表元素为 (1,2,3,4,5,5,6,7,8,8,9,9,9,9,9)

4.

递增有序单链表L1、L2,不申请新结点,利用原表结点对两表进行合并,并使得合并后成为一个集合,合并后用L1的头结点作为头结点,删除多余的结点,删除L2的头结点。要求时间性能最好。

实验测试数据基本要求:

第一组

第一个单链表元素为 (1,3,6,10,15,16,17,18,19,20)

第二个单链表元素为 (1,2,3,4,5,6,7,8,9,10,18,20,30)

第二组

第一个单链表元素为 (1,3,6,10,15,16,17,18,19,20)

第二个单链表元素为 (2,4,5,7,8,9,12,22)

第三组

第一个单链表元素为 ()

第二个单链表元素为 (1,2,3,4,5,6,7,8,9,10)

5.

已知一个带有表头结点的单链表,结点结构如下图。假设该链表只给出了头指针list。在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点的data值,并返回1;否则,只返回0。要求:

(1)描述算法的基本设计思想

(2)描述算法的详细实现步骤

(3)根据设计思想和实现步骤,采用程序设计语言描述算法(使用C 或C++语言实现),关键之处请给出简要注释。

4.数据结构设计

// 定义单链表的节点结构体  
typedef struct slNode  
{  
    int data;       // 节点存储的数据  
    slNode *next;   // 指向下一个节点的指针  
} node, *linkList;  // node为节点类型,linkList为指向节点的指针类型  

5.算法设计

1.

【算法设计思想】
  1. 创建两个新的链表头节点,分别表示奇数链表和偶数链表。
  2. 初始化指针p1和p2分别指向奇数链表和偶数链表的尾部。
  3. 使用指针p遍历原链表,根据节点数据的奇偶性创建新节点,并将新节点添加到对应的奇数链表或偶数链表的尾部。
  4. 更新奇数链表和偶数链表的尾指针。
  5. 继续遍历原链表,直到所有节点处理完毕。
【算法描述】
// 奇偶分类函数  
// 参数L为原链表的头指针,L1为奇数链表的头指针,L2为偶数链表的头指针  
void classification(linkList L, linkList &L1, linkList &L2)  
{  
    L1 = new node;  // 创建奇数链表的头节点  
    L1->next = NULL;  
    L2 = new node;  // 创建偶数链表的头节点  
    L2->next = NULL;  
  
    node *p1 = L1;  // p1作为奇数链表的尾指针  
    node *p2 = L2;  // p2作为偶数链表的尾指针  
    node *p = L->next;  // p遍历原链表  
  
    // 遍历原链表,根据节点数据的奇偶性分别添加到奇数链表和偶数链表中  
    while (p)  
    {  
        node *u = new node;  // 创建新节点  
        u->data = p->data;  // 设置新节点的数据  
        u->next = NULL;  // 新节点的下一个节点为空  
  
        if (p->data % 2)  // 如果节点数据为奇数  
        {  
            p1->next = u;  // 将新节点添加到奇数链表尾部  
            p1 = p1->next;  // 更新奇数链表的尾指针  
        }  
        else  // 如果节点数据为偶数  
        {  
            p2->next = u;  // 将新节点添加到偶数链表尾部  
            p2 = p2->next;  // 更新偶数链表的尾指针  
        }  
  
        p = p->next;  // 继续遍历原链表  
    }  
}  

2.

【算法设计思想】
  1. 创建一个新的链表L3,用于存储公共元素。
  2. 初始化指针u,i和j,分别用于遍历新链表L3、链表L1和链表L2。
  3. 遍历链表L1和L2,比较它们的元素:
    1. 如果L1中的元素大于L2中的元素,则移动L2的遍历指针。
    2. 如果L1中的元素小于L2中的元素,则移动L1的遍历指针。
    3. 如果L1和L2中的元素相等,则将该元素添加到新链表L3中,并更新指针u,i和j。
【算法描述】
// 寻找重复元素函数  
// 参数L1和L2为两个链表的头指针,返回包含公共元素的链表头指针  
linkList findSame(linkList L1, linkList L2)  
{  
    linkList L3 = new node;  // 创建新链表L3,用于存储公共元素  
    L3->next = NULL;  
  
    node* u = L3;  // u作为新链表L3的尾指针  
    node* i = L1->next;  // i遍历链表L1  
    node* j = L2->next;  // j遍历链表L2  
    // 遍历L1和L2  
    while (i != NULL && j != NULL)  
    {  
        if (i->data > j->data)  // 如果L1中的元素大于L2中的元素  
        {  
            j = j->next;  // 移动L2的遍历指针  
        }  
        else if (i->data < j->data)  // 如果L1中的元素小于L2中的元素  
        {  
            i = i->next;  // 移动L1的遍历指针  
        }  
        else  // 如果L1和L2中的元素相等  
        {  
            node* r = new node;  // 创建新节点  
            r->data = i->data;  // 设置新节点的数据  
            r->next = NULL;  // 新节点的下一个节点为空  
            u->next = r;  // 将新节点添加到L3尾部  
  
            u = r;  // 更新L3的尾指针  
            i = i->next;  // 移动L1的遍历指针  
            j = j->next;  // 移动L2的遍历指针  
        }  
    }  
  
    return L3;  // 返回包含公共元素的链表L3  
}  

3.

【算法设计思想】
  1. 首先,检查链表的长度是否小于2,如果是,则无需去重,直接返回false。
  2. 然后,初始化两个指针b和f,其中b作为慢指针,f作为快指针,分别指向链表的第一个元素和第二个元素。
  3. 接下来,使用一个临时节点temp来删除重复元素。在一个while循环中,不断比较快指针f指向的元素和慢指针b指向的元素,如果它们不相等,则将不重复的元素连接到链表,并更新慢指针b和快指针f。
  4. 如果发现重复元素,就将重复元素的指针保存到temp中,然后更新快指针f,同时删除重复元素。
  5. 然后,将慢指针b的next指针指向快指针f,以确保链表的末尾正确连接。
  6. 最后,返回true,表示去重成功。
【算法描述】
// 从链表中删除重复的元素  
// 参数L为链表的头指针,如果去重成功返回true,否则返回false  
bool removeDuplicates(linkList L)  
{  
    // 如果列表长度小于2,无需去重  
    if (L->next->next == NULL) return false;  
  
    // 初始化索引  
    node* b = L->next;  // b作为慢指针  
    node* f = b->next;  // f作为快指针  
    node *temp;  // 临时节点用于删除重复元素  
    while (f != NULL)  
    {  
        // 如果当前元素不等于索引处的元素,说明找到了一个新的不重复元素  
        if (f->data != b->data)  
        {  
            b->next = f;  // 将不重复的元素连接到链表  
            b = f;  // 更新慢指针  
            f = f->next;  // 更新快指针  
            continue;  
        }  
  
        temp = f;  // 保存重复元素的指
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值