上机实验二 设计单循环链表 西安石油大学数据结构

简介: 上机实验二 设计单循环链表 西安石油大学数据结构

实验名称:设计单循环链表

(1)实验目的:掌握线性表的链式存储结构;掌握单循环链表及其基本操作的实现。

(2)主要内容:实现单循环链表的初始化、求数据元素个数、插入、删除、取数据元素等操作;用插入法建立带头结点的单循环链表;设计一个测试主函数验证所设计单循环链表的正确性。

1.实验目的

掌握线性表的链式存储结构;掌握单循环链表及其基本操作的实现。

2.问题描述

利用C语言设计实现单循环链表,并实现初始化、求数据元素个数、插入、删除、取数据元素等基本操作。使用插入法建立带头结点的单循环链表,并设计一个测试主函数验证所设计单循环链表的正确性。

3.基本要求

具体要求如下:

  1. 设计一个结构体表示链表的节点,包括数据域和指针域。
  2. 实现单循环链表的初始化操作,即创建一个空链表。
  3. 实现求数据元素个数的操作,即统计链表中已有的节点数。
  4. 实现插入操作,在指定位置插入一个节点,并将新节点链接到链表中。
  5. 实现删除操作,删除指定位置的节点。
  6. 实现取数据元素的操作,返回指定位置的节点值。
  7. 使用插入法建立带头结点的单循环链表,即通过用户输入逐个插入节点来创建链表,直到用户结束输入。
  8. 编写一个测试主函数,验证所设计单循环链表的正确性,包括对各个操作的测试。测试包括但不限于以下内容:创建一个空链表并输出链表元素个数。
    插入若干节点,并验证插入后链表的正确性。
    删除某个位置的节点,并验证删除后链表的正确性。
    取某个位置的节点值,并输出验证结果。

4.测试数据

初始链表为空,链表元素个数为:0

插入后的链表元素:10

插入后的链表元素:5 15 10 20

删除后的链表元素:15 20

取节点值的结果:

Position 0: 15

Position 1: 20

Position 2: -1

5.算法思想

链表数据结构的基本操作,包括初始化链表、获取链表元素个数、在指定位置插入节点、删除指定位置的节点、获取指定位置节点的值以及打印链表中的元素。其中,链表是一种线性结构,每个节点包括数据和指向下一个节点的指针,头结点不包含数据。

该算法通过遍历链表的方式来找到指定位置的节点,然后进行相应的操作。具体实现方法包括:在空链表中插入第一个节点时,直接将头结点指向新节点;在链表头部插入节点时,将新节点的指针指向原头结点,再将头结点指向新节点;在链表中间和尾部插入节点时,在找到插入位置的前一个节点后,将新节点的指针指向原位置的节点,再将前一个节点的指针指向新节点;删除节点时,首先找到要删除节点的前一个节点,将前一个节点的指针指向要删除节点的下一个节点,然后释放要删除节点的内存空间;获取节点值时,找到指定位置的节点,返回其数据域的值。

6.模块划分

  1. initList():初始化链表,返回头结点。
  2. listLength(Node* head):获取链表的元素个数。
  3. insertNode(Node* head, int position, int data):在链表指定位置插入节点。
  4. deleteNode(Node* head, int position):删除链表指定位置的节点。
  5. getNodeData(Node* head, int position):获取链表指定位置节点的值。
  6. printList(Node* head):打印链表中的元素。
  7. main():主函数。

7.数据结构

(1) 数据类型DataType定义如下:

typedef struct {
    int number;
    int cipher;
} DataType;

这个定义表示DataType结构体包含两个成员变量,即numbercipher,分别表示一个整数的数字和位数。

(2) 带头结点单循环链表结点的结构体定义如下:

typedef struct SCLNode {
    DataType data;
    struct SCLNode* next;
} SCLNode;

这个定义表示SCLNode结构体是一个带头结点的单循环链表的节点,包含两个成员变量。其中,data是存储数据元素的DataType类型的变量。next是指向下一个节点的指针,类型为指向SCLNode结构体的指针。

通过这样的定义,可以创建一个带头结点的单循环链表,每个节点存储一个数据元素,并且通过next指针连接起来形成循环链表。头结点的作用是指示链表的起始位置,尾节点的next指针指向头结点,形成循环。

8.源程序

#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
    int data;
    struct Node* next;
} Node;
// 初始化链表,返回头结点
Node* initList() {
    Node* head = (Node*)malloc(sizeof(Node));
    head->next = NULL;  // 初始化时头结点指向NULL,形成空链表
    return head;
}
// 获取链表的元素个数
int listLength(Node* head) {
    int count = 0;
    Node* current = head->next;
    while (current != NULL) {
        count++;
        current = current->next;
    }
    return count;
}
// 在链表指定位置插入节点
void insertNode(Node* head, int position, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    Node* current = head;
    int count = 0;
    while (current != NULL && count < position) {
        current = current->next;
        count++;
    }
    newNode->next = current->next;
    current->next = newNode;
}
// 删除链表指定位置的节点
void deleteNode(Node* head, int position) {
    Node* current = head;
    int count = 0;
    while (current->next != NULL && count < position) {
        current = current->next;
        count++;
    }
    if (current->next != NULL) {
        Node* temp = current->next;
        current->next = temp->next;
        free(temp);
    }
}
// 获取链表指定位置节点的值
int getNodeData(Node* head, int position) {
    Node* current = head->next;
    int count = 0;
    while (current != NULL && count < position) {
        current = current->next;
        count++;
    }
    if (current != NULL)
        return current->data;
    else
        return -1;  // 返回-1表示节点不存在
}
// 打印链表中的元素
void printList(Node* head) {
    Node* current = head->next;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}
int main() {
    Node* head = initList();
    printf("初始链表为空,链表元素个数为:%d\n", listLength(head));
    insertNode(head, 0, 10);  // 在空链表中插入第一个节点
    printf("插入后的链表元素:");
    printList(head);
    insertNode(head, 0, 5);  // 在链表头部插入节点
    insertNode(head, 1, 15); // 在链表中间插入节点
    insertNode(head, 3, 20); // 在链表尾部插入节点
    printf("插入后的链表元素:");
    printList(head);
    deleteNode(head, 0); // 删除头结点
    deleteNode(head, 1); // 删除链表中的某个节点
    deleteNode(head, 2); // 删除尾节点
    printf("删除后的链表元素:");
    printList(head);
    int data1 = getNodeData(head, 0); // 取链表头结点的数据
    int data2 = getNodeData(head, 1); // 取链表中间某个节点的数据
    int data3 = getNodeData(head, 2); // 取链表尾节点的数据
    printf("取节点值的结果:\n");
    printf("Position 0: %d\n", data1);
    printf("Position 1: %d\n", data2);
    printf("Position 2: %d\n", data3);
    return 0;
}

9.测试情况

进行测试结果分析

初始化链表后,链表为空,元素个数为0。

在空链表中插入第一个节点,插入后的链表元素为10。可以看到插入操作正常。

在链表头部插入节点5,链表中间插入节点15,链表尾部插入节点20。插入后的链表元素为5 15 10 20。可以看到在不同位置插入节点的操作正常。

删除头结点,删除链表中的某个节点,删除尾节点。删除后的链表元素为5 10。可以看到删除操作正常。

取链表头结点的数据,取链表中间某个节点的数据,取链表尾节点的数据。取节点值的结果如下:

Position 0: 5

Position 1: 10

Position 2: -1

可以看到,成功获取了节点的值,并且当位置越界时返回了-1。说明获取节点值的功能正常。

综上所述,根据测试结果,代码实现了链表的基本操作,并且功能正常。

描述存在的问题及建议

存在的问题是在插入和删除节点时没有进行越界检查,可能导致访问非法内存。建议在插入和删除节点的代码中增加对位置的合法性检查,确保不会越界。

另外,代码中的打印函数printList()可以优化,避免每次都要遍历整个链表才能打印出结果。可以考虑在插入、删除和修改节点时维护链表的长度,并在需要打印时直接使用链表长度进行循环打印。这样可以提高效率。

目录
相关文章
|
1月前
|
存储 算法 编译器
数据结构实验之矩阵的运算器(二维数组)
本实验旨在通过团队合作,掌握数组和矩阵相关运算的代码实现,包括矩阵的加减、数乘、转置、乘法、n次方及行列式的计算。实验过程中,成员们需分工协作,解决编程难题,最终实现一个功能完备的矩阵计算器。通过本实验,不仅锻炼了编程能力,还加深了对数学概念的理解,同时培养了团队合作精神。
57 4
|
1月前
数据结构实验之串模式匹配问题
本实验旨在掌握串模式匹配技术,通过创建文本文件、实现单词计数与定位功能,最终构建一个包含文件建立、单词统计与定位、程序退出等选项的主菜单,以增强对字符串处理的理解与应用能力。
45 4
|
1月前
|
算法
数据结构实验之最长公共子序列
本实验旨在通过编程实践帮助学生理解串的基本概念及求解最长公共子序列的算法。实验内容包括使用动态规划方法设计并实现算法,以找出给定两序列的最大公共子序列。示例代码展示了如何通过构建状态矩阵和回溯路径来找到解决方案。实验总结指出,`memset()`函数用于内存初始化,且对于特定输入,程序能正确输出最长公共子序列之一。
52 4
|
1月前
|
算法
数据结构实验之操作系统打印机管理器问题
本实验旨在通过实现操作系统中的打印机管理器问题,掌握队列的基本操作如入队、出队等,利用队列的先进先出特性解决先申请先打印的问题。实验包括队列的初始化、入队、出队、打印队列内容等功能,并通过菜单式界面进行交互。实验结果显示基本功能可正常执行,但在连续操作时存在执行失败的情况,需进一步优化。
42 4
|
1月前
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
55 4
|
1月前
|
机器学习/深度学习 存储 算法
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
81 4
|
1月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
51 4
|
1月前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
57 0
|
2月前
数据结构的带头,双向,循环链表来咯
数据结构的带头,双向,循环链表来咯
19 0
|
2月前
|
算法
计科一二班算法数据结构实验9答案
计科一二班算法数据结构实验9答案
19 0