单链表操作—学生成绩管理

引言

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

目录

引言

结点信息类的构造

链表类的构造

链表类方法的构造

判断链表是否为空

在链表尾部插入新结点

在链表表头插入新结点

在第index处插入新结点

删除当前链表中对象的首元结点

删除当前链表中对象的尾结点

删除第index个结点

更新第index结点的值

获取第index节点的值

获取元素i在结点对象的引用

清空链表

打印链表

读取txt文件数据,并存入数组

将链表的数据写入txt文件中

完整代码


结点信息类的构造

class student:                                    #结点信息类
    def __init__(self, no, name, Math,Eng):        # 构造函数,初始化变量
        self.no = no                                # 学号
        self.name = name                            # 姓名
        self.suxue = Math                           # 数学成绩
        self.yingyu = Eng                           # 英语成绩
        self.next = None                            #创建指针

    def __repr__(self):                                                                                  # 输出结点的格式
        return str(self.no) + "\t\t" + str(self.name) + "\t\t" + str(self.suxue) + "\t\t" + str(self.yingyu)   #将信息类型转化为字符串

链表类的构造

class ListXS:                                             #生成链表类
    def __init__(self):                                    #初始化单链表
        self.headnode = student(None,None,None,None)        #创建头结点
        self.headnode.next = None                           #头结点指针

链表类方法的构造

判断链表是否为空

    def is_empty(self):                                             #判断链表是否为空
        return self.headnode.next is None                            #判断链表长度是否等于0

在链表尾部插入新结点

    def append(self,no, name, Math,Eng):                   #在链表尾部插入新结点
        this_node = student(no, name, Math,Eng)             #创建新结点
        p = self.headnode                                   #获取链表位置
        while p.next:                                       #循环获取第i位前一个的结点
            p = p.next                                      #更新p的值
        this_node.next = p.next                             #新结点指针指向None
        p.next = this_node                                  #将原链表指针指向新结点

在链表表头插入新结点

    def front_add(self,no, name, Math,Eng):                #在链表表头插入新结点
        this_node = student(no, name, Math,Eng)             #创建新结点
        p = self.headnode                                   #获取链表位置
        this_node.next = self.headnode.next                 #将链表的首元结点设置为新结点
        self.headnode.next = this_node                      #新链表首元结点的指针域指向原链表的首元结点

在第index处插入新结点

    def insert(self,no, name, Math,Eng, index):            #在第index处插入新结点
        this_node = student(no, name, Math,Eng)             #创建新结点
        p = self.headnode                                   #获取原链表首元结点
        while index:                                        #循环获取第i位前一个的结点
            p = p.next                                      #更新p的值
            index -= 1                                      #更新循环的条件
        this_node.next = p.next                             #新结点指针指向原链表第i位置的结点
        p.next = this_node                                  #原链表第i-1位置的结点的指针指向新结点

删除当前链表中对象的首元结点

    def pop_front(self):                                   #删除当前链表中对象的首元结点
        if self.headnode.next == None:                      #判断链表是否为空
            print("Error")                                  #如果链表为空,则操作失败
            print('请输入正确的操作:')                         #重新输入操作
        else:                                               #如果链表含有一个或一个以上的结点,则执行以下操作
            p = self.headnode.next.next                     #获取原链表首元结点的下一个结点信息
            self.headnode.next = p                          #将原链表首元结点下一个结点作为首元结点

删除当前链表中对象的尾结点

    def pop_back_bad(self):                                #删除当前链表中对象的尾结点
        if self.headnode.next == None:                      #判断链表是否为空
            print("Error")                                  #如果链表为空,则操作失败
            print('请输入正确的操作:')                         #重新输入操作
        elif self.headnode.next.next == None:               #判断链表中是否只包含一个结点
            self.headnode.next = None                       #将头结点的指针指向None
        else:                                               #判断链表是否含有一个以上的结点
            p = self.headnode                               #获取链表位置
            while p.next.next != None:                      #循环获取尾结点前一个的结点
                p = p.next                                  #更新p的值
            p.next = None                                   #将尾结点前一个的结点的指针指向None

删除第index个结点

    def delete(self, index):                               #删除第index个结点
        if self.headnode.next == None:                      #判断链表是否为空
            print("Error")                                  #如果链表为空,则操作失败
            print('请输入正确的操作:')                         #重新输入操作
        elif index == 0:                                    #判断删除位置index是否在链表表头
            self.headnode.next = self.headnode.next.next    #将头结点的指针指向原链表首元结点的下一个结点
        else:                                               #删除位置不在链表表头
            p = self.headnode                               #获取链表位置
            while index:                                    #循环获取第i位前一个的结点
                p = p.next                                  #更新p的值
                index -= 1                                  #更新循环的条件
            p.next = p.next.next                            #将第i-1位置的结点的指针指向i位置的下一个结点

更新第index结点的值

    def update(self, data, index):                         #更新第index结点的值
        if index == 0:                                      #判断更新位置index是否在链表表头
            data.next = self.headnode.next.next             #将
            self.headnode.next = data                       #如果链表只有一个结点,则将该结点的数据域改为data
        else:                                               #如果链表存在一个结点以上,则执行以下操作
            p = self.headnode                                   #获取原链表首元结点
            while index:                                    #循环获取第i位的结点
                p = p.next                                  #更新p的值
                index -= 1                                  #更新循环的条件
            data.next = p.next.next
            p.next = data

获取第index节点的值

    def get_data(self, index):                             #获取第index节点的值
        if index == 0:                                      #判断获取位置index是否在链表表头
            print(self.headnode.next)                       #如果链表只有一个结点,则返回该结点的数据域
        else:                                               #如果链表存在一个结点以上,则执行以下操作
            p = self.headnode                                  #获取原链表首元结点
            while index:                                    #循环获取第i位的结点
                p = p.next                                  #更新p的值
                index -= 1                                  #更新循环的条件
            print(p.next)                                   #输出获取的结点

获取元素i在结点对象的引用

    def search(self,i):                                    #获取元素i在结点对象的引用
        p = self.headnode                                      #获取原链表首元结点
        while p.next and str(p.next) != str(i):                  #循环找到结点数据域等于i的结点
            p = p.next                                      #更新p的值
        print(p.next)                                       #输出获取的结点
        return p.next                                       #返回结点引用

清空链表

    def clear(self):                                       #清空链表
        self.headnode.next = None                                    #链表头指针指向None
        print('True')                                       #清空链表成功

打印链表

    def PrintList(self):                                   #打印链表
        if self.headnode.next == None:                               #判断链表是否为空表
            return None                                     #如果链表为空,则返回None
        else:                                               #如果链表不为空,则执行以下操作
            p = self.headnode                                   #获取原链表首元结点
            while p.next:                                   #将链表循环一次
                p = p.next                                  #更新p的值
                print(p)                                   #输出每个结点的数据域
            return p                                   #返回每个结点的数据域

读取txt文件数据,并存入数组

    def ReadFromFile(self,txt_path):                                    #读取txt文件数据,并存入数组
        with open(r"{0}".format(txt_path), "r",encoding='utf-8') as f:     #读取txt文件里的数据
            next(f)                                                 # 跳过第一行内容读入
            row = f.readlines()                                     #读取每一行的数据
        a = []
        for i in range(len(row)):
            num_row = row[i].strip().split(",")                     # strip():移除字符串头尾指定的字符(默认为空格或换行符)或字符序列,split():指定分隔符对字符串进行切片
            a.append(num_row)
        return a                                                    #返回整个数组

将链表的数据写入txt文件中

    def Writer_data(self,address):                                         #将链表的数据写入txt文件中
        with open(r"{0}".format(address), "w", encoding='utf-8') as f:      #储存路径
            f.write('学号		           姓名         数学成绩     英语成绩'+'\n')
            p = self.headnode.next                                                   # 获取原链表首元结点
            while p.next:                                                   #将链表循环一次
                f.write(str(p)+'\n')                                   #将链表中的数据写入txt文件中
                p = p.next                                                  #更新循环条件
        print('True')                                                       #写入成功

完整代码

class student:                                    #结点信息类
    def __init__(self, no, name, Math,Eng):        # 构造函数,初始化变量
        self.no = no                                # 学号
        self.name = name                            # 姓名
        self.suxue = Math                           # 数学成绩
        self.yingyu = Eng                           # 英语成绩
        self.next = None                            #创建指针

    def __repr__(self):                                                                                  # 输出结点的格式
        return str(self.no) + "\t\t" + str(self.name) + "\t\t" + str(self.suxue) + "\t\t" + str(self.yingyu)   #将信息类型转化为字符串

class ListXS:                                             #生成链表类
    def __init__(self):                                    #初始化单链表
        self.headnode = student(None,None,None,None)        #创建头结点
        self.headnode.next = None                           #头结点指针

    def is_empty(self):                                             #判断链表是否为空
        return self.headnode.next is None                            #判断链表长度是否等于0

    def append(self,no, name, Math,Eng):                   #在链表尾部插入新结点
        this_node = student(no, name, Math,Eng)             #创建新结点
        p = self.headnode                                   #获取链表位置
        while p.next:                                       #循环获取第i位前一个的结点
            p = p.next                                      #更新p的值
        this_node.next = p.next                             #新结点指针指向None
        p.next = this_node                                  #将原链表指针指向新结点

    def front_add(self,no, name, Math,Eng):                #在链表表头插入新结点
        this_node = student(no, name, Math,Eng)             #创建新结点
        p = self.headnode                                   #获取链表位置
        this_node.next = self.headnode.next                 #将链表的首元结点设置为新结点
        self.headnode.next = this_node                      #新链表首元结点的指针域指向原链表的首元结点

    def insert(self,no, name, Math,Eng, index):            #在第index处插入新结点
        this_node = student(no, name, Math,Eng)             #创建新结点
        p = self.headnode                                   #获取原链表首元结点
        while index:                                        #循环获取第i位前一个的结点
            p = p.next                                      #更新p的值
            index -= 1                                      #更新循环的条件
        this_node.next = p.next                             #新结点指针指向原链表第i位置的结点
        p.next = this_node                                  #原链表第i-1位置的结点的指针指向新结点

    def pop_front(self):                                   #删除当前链表中对象的首元结点
        if self.headnode.next == None:                      #判断链表是否为空
            print("Error")                                  #如果链表为空,则操作失败
            print('请输入正确的操作:')                         #重新输入操作
        else:                                               #如果链表含有一个或一个以上的结点,则执行以下操作
            p = self.headnode.next.next                     #获取原链表首元结点的下一个结点信息
            self.headnode.next = p                          #将原链表首元结点下一个结点作为首元结点

    def pop_back_bad(self):                                #删除当前链表中对象的尾结点
        if self.headnode.next == None:                      #判断链表是否为空
            print("Error")                                  #如果链表为空,则操作失败
            print('请输入正确的操作:')                         #重新输入操作
        elif self.headnode.next.next == None:               #判断链表中是否只包含一个结点
            self.headnode.next = None                       #将头结点的指针指向None
        else:                                               #判断链表是否含有一个以上的结点
            p = self.headnode                               #获取链表位置
            while p.next.next != None:                      #循环获取尾结点前一个的结点
                p = p.next                                  #更新p的值
            p.next = None                                   #将尾结点前一个的结点的指针指向None

    def delete(self, index):                               #删除第index个结点
        if self.headnode.next == None:                      #判断链表是否为空
            print("Error")                                  #如果链表为空,则操作失败
            print('请输入正确的操作:')                         #重新输入操作
        elif index == 0:                                    #判断删除位置index是否在链表表头
            self.headnode.next = self.headnode.next.next    #将头结点的指针指向原链表首元结点的下一个结点
        else:                                               #删除位置不在链表表头
            p = self.headnode                               #获取链表位置
            while index:                                    #循环获取第i位前一个的结点
                p = p.next                                  #更新p的值
                index -= 1                                  #更新循环的条件
            p.next = p.next.next                            #将第i-1位置的结点的指针指向i位置的下一个结点

    def update(self, data, index):                         #更新第index结点的值
        if index == 0:                                      #判断更新位置index是否在链表表头
            data.next = self.headnode.next.next             #将
            self.headnode.next = data                       #如果链表只有一个结点,则将该结点的数据域改为data
        else:                                               #如果链表存在一个结点以上,则执行以下操作
            p = self.headnode                                   #获取原链表首元结点
            while index:                                    #循环获取第i位的结点
                p = p.next                                  #更新p的值
                index -= 1                                  #更新循环的条件
            data.next = p.next.next
            p.next = data

    def get_data(self, index):                             #获取第index节点的值
        if index == 0:                                      #判断获取位置index是否在链表表头
            print(self.headnode.next)                       #如果链表只有一个结点,则返回该结点的数据域
        else:                                               #如果链表存在一个结点以上,则执行以下操作
            p = self.headnode                                  #获取原链表首元结点
            while index:                                    #循环获取第i位的结点
                p = p.next                                  #更新p的值
                index -= 1                                  #更新循环的条件
            print(p.next)                                   #输出获取的结点

    def search(self,i):                                    #获取元素i在结点对象的引用
        p = self.headnode                                      #获取原链表首元结点
        while p.next and str(p.next) != str(i):                  #循环找到结点数据域等于i的结点
            p = p.next                                      #更新p的值
        print(p.next)                                       #输出获取的结点
        return p.next                                       #返回结点引用

    def clear(self):                                       #清空链表
        self.headnode.next = None                                    #链表头指针指向None
        print('True')                                       #清空链表成功
    #
    def PrintList(self):                                   #打印链表
        if self.headnode.next == None:                               #判断链表是否为空表
            return None                                     #如果链表为空,则返回None
        else:                                               #如果链表不为空,则执行以下操作
            p = self.headnode                                   #获取原链表首元结点
            while p.next:                                   #将链表循环一次
                p = p.next                                  #更新p的值
                print(p)                                   #输出每个结点的数据域
            return p                                   #返回每个结点的数据域

    def ReadFromFile(self,txt_path):                                    #读取txt文件数据,并存入数组
        with open(r"{0}".format(txt_path), "r",encoding='utf-8') as f:     #读取txt文件里的数据
            next(f)                                                 # 跳过第一行内容读入
            row = f.readlines()                                     #读取每一行的数据
        a = []
        for i in range(len(row)):
            num_row = row[i].strip().split(",")                     # strip():移除字符串头尾指定的字符(默认为空格或换行符)或字符序列,split():指定分隔符对字符串进行切片
            a.append(num_row)
        return a                                                    #返回整个数组

    def Writer_data(self,address):                                         #将链表的数据写入txt文件中
        with open(r"{0}".format(address), "w", encoding='utf-8') as f:      #储存路径
            f.write('学号		           姓名         数学成绩     英语成绩'+'\n')
            p = self.headnode.next                                                   # 获取原链表首元结点
            while p.next:                                                   #将链表循环一次
                f.write(str(p)+'\n')                                   #将链表中的数据写入txt文件中
                p = p.next                                                  #更新循环条件
        print('True')                                                       #写入成功


def main():                                 #测试和调试
    a =True
    data = ListXS()
    while a:
        a = input('请选择你想要实现链表的功能:'+'\n'+'1.在链表尾部插入新结点'+'\n'+'2.在链表表头插入新结点'+'\n'+'3.在指定位置index处插入新结点'+'\n'+'4.删除当前链表中对象的首元结点'+'\n'+'5.删除当前链表中对象的尾结点'+'\n'+'6.删除指定index位置的结点'+'\n'+'7.更新第index结点的值'+'\n'+'8.获取第index结点的值'+'\n'+'9.获取元素i在结点对象的引用'+'\n'+'10.判断链表是否为空'+'\n'+'11.清空链表'+'\n'+'12.打印链表'+'\n'+'13.读取txt文件数据,并存入链表'+'\n'+'14.将链表的数据写入txt文件中'+'\n'+'15.结束操作'+'\n'+'请输入你的操作:')
        if a == '1':
            print("------------------在链表尾部插入新结点-----------------------------")
            z,x,c,v = input('请输入插入新结点信息并用,分隔:').split(',')
            data.append(z,x,c,v)
            data.PrintList()
        elif a == '2':
            print("------------------在链表头部插入新结点-----------------------------")
            z,x,c,v = input('请输入插入新结点信息并用,分隔:').split(',')
            data.front_add(z,x,c,v)
            data.PrintList()
        elif a == '3':
            print("---------------------向指定位置插入新结点结点-----------------------------")
            z, x, c, v = input('请输入插入新结点信息并用,分隔:').split(',')
            b = int(input('请输入插入位置:'))
            data.insert(z,x,c,v,b)
            data.PrintList()
        elif a == '4':
            print("------------------删除首元结点-----------------------------")
            data.pop_front()
            data.PrintList()
        elif a == '5':
            print("------------------删除尾结点-----------------------------")
            data.pop_back_bad()
            data.PrintList()
        elif a == '6':
            print("---------------------删除指定位置的结点-----------------------------")
            z = int(input("请输入删除结点的位置:"))
            data.delete(z)
            data.PrintList()
        elif a == '7':
            print("--------------------------更新第index结点的值----------------------------------")
            z, x, c, v = input('请输入新结点信息并用,分隔:').split(',')
            b = int(input('请输入更新位置:'))
            data.update(student(z,x,c,v),b)
            data.PrintList()
        elif a == '8':
            print("---------------------获取第index位置的结点值-----------------------------")
            z = int(input('请输入获取位置:'))
            data.get_data(z)
        elif a == '9':
            print("---------------------获取第index结点对象的引用-----------------------------")
            z, x, c, v = input('请输入查找信息:').split(',')
            data.search(student(z,x,c,v))
        elif a == '10':
            print("--------------------------判断链表是否为空----------------------------------")
            print(data.is_empty())
        elif a == '11':
            print("--------------------------将链表中清空----------------------------------")
            data.clear()
        elif a == '12':
            print("--------------------------打印链表----------------------------------")
            data.PrintList()
        elif a == '13':
            print("------------------读取txt文件数据,将数据加入到链表中-----------------------------")
            z = input("请输入txt文件名:")
            for i in data.ReadFromFile(z):
                data.append(i[0], i[1], i[2], i[3])
            data.PrintList()
        elif a == '14':
            print("--------------------------将链表中的数据保存到txt文件中----------------------------------")
            z = input('请输入保存txt文件名')
            data.Writer_data(z)
        elif a == '15':
            print('--------------------------结束链表操作------------------------------')
            a = False
        else:
            print('输入错误,请重新输入:')
            continue

if __name__ == '__main__':                  #如果name等于main则运行
    main()                                  #运行main

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我们可以定义一个结构体来表示学生信息和成绩,然后使用链表来管理这些数据。 首先,我们定义结构体 `Student`: ```c typedef struct student { char name[20]; int id; float score; struct student *next; } Student; ``` 其中,`name` 表示学生姓名,`id` 表示学生学号,`score` 表示学生成绩,`next` 表示指向下一个节点的指针。 然后,我们需要实现以下操作: 1. 添加一个学生节点 2. 删除一个学生节点 3. 修改一个学生节点的信息 4. 查找一个学生节点的信息 5. 输出所有学生的信息 接下来,我们逐个实现这些操作。 1. 添加一个学生节点 ```c Student *addStudent(Student *head) { Student *p = (Student *)malloc(sizeof(Student)); printf("Enter student name, id, score:\n"); scanf("%s %d %f", p->name, &p->id, &p->score); p->next = head; head = p; return head; } ``` 这里使用了 `malloc` 动态分配内存来创建新节点,然后在键盘输入学生信息,并将节点插入链表头部。 2. 删除一个学生节点 ```c Student *deleteStudent(Student *head, int id) { Student *p = head; Student *pre = NULL; while (p != NULL && p->id != id) { pre = p; p = p->next; } if (p == NULL) { printf("No such student.\n"); return head; } if (pre == NULL) { head = head->next; } else { pre->next = p->next; } free(p); return head; } ``` 这里使用了指针变量 `pre` 来记录当前节点的前一个节点,以便在删除节点时修改链表指针。 3. 修改一个学生节点的信息 ```c void modifyStudent(Student *head, int id) { Student *p = head; while (p != NULL && p->id != id) { p = p->next; } if (p == NULL) { printf("No such student.\n"); return; } printf("Enter new name, id, score:\n"); scanf("%s %d %f", p->name, &p->id, &p->score); } ``` 直接使用指针变量 `p` 在链表中查找到需要修改的节点,然后键盘输入修改后的学生信息。 4. 查找一个学生节点的信息 ```c void findStudent(Student *head, int id) { Student *p = head; while (p != NULL && p->id != id) { p = p->next; } if (p == NULL) { printf("No such student.\n"); return; } printf("Name: %s\n", p->name); printf("ID: %d\n", p->id); printf("Score: %f\n", p->score); } ``` 同样是使用指针变量 `p` 在链表中查找到需要查询的节点,并输出学生信息。 5. 输出所有学生的信息 ```c void printAll(Student *head) { Student *p = head; while (p != NULL) { printf("Name: %s\n", p->name); printf("ID: %d\n", p->id); printf("Score: %f\n", p->score); p = p->next; } } ``` 顺序遍历整个链表,并输出每个节点的学生信息。 最后,我们可以在 `main` 函数中调用这些操作来实现完整的学生成绩管理系统。 ```c int main() { Student *head = NULL; int choice = 0; int id = 0; while (1) { printf("1. Add student\n"); printf("2. Delete student\n"); printf("3. Modify student\n"); printf("4. Find student\n"); printf("5. Print all students\n"); printf("0. Exit\n"); scanf("%d", &choice); switch (choice) { case 1: head = addStudent(head); break; case 2: printf("Enter student id:\n"); scanf("%d", &id); head = deleteStudent(head, id); break; case 3: printf("Enter student id:\n"); scanf("%d", &id); modifyStudent(head, id); break; case 4: printf("Enter student id:\n"); scanf("%d", &id); findStudent(head, id); break; case 5: printAll(head); break; case 0: return 0; default: printf("Invalid choice.\n"); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

!continue!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值