`

C#实现双向链表

 
阅读更多
/// <summary>
    /// 双向链表节点类
    /// </summary>
    /// <typeparam name="T">节点中的存放的数据类型</typeparam>
    public class Node<T>
    {
        /// <summary>
        /// 当前节点的数据
        /// </summary>
        T data;
        /// <summary>
        /// 节点中存放的数据
        /// </summary>
        public T Data
        {
            get { return this.data; }
            set { this.data = value; }
        }
        /// <summary>
        /// 当前节点的下一个节点
        /// </summary>
        Node<T> next;
        /// <summary>
        /// 下一个节点
        /// </summary>
        public Node<T> Next
        {
            get { return this.next; }
            set { this.next = value; }
        }
        /// <summary>
        /// 当前节点的上一个节点
        /// </summary>
        Node<T> prev;
        /// <summary>
        /// 上一个节点
        /// </summary>
        public Node<T> Prev
        {
            get { return prev; }
            set { prev = value; }
        }
        /// <summary>
        /// 无参构造:数据为默认值,下一个节点为null,上一个节点也为null
        /// </summary>
        public Node()
        {
            this.data = default(T);
            this.next = null;
            this.prev = null;
        }
        /// <summary>
        /// 构造方法:数据为传过来的t,下一个节点为null,上一个节点也为null
        /// </summary>
        /// <param name="t">传入的元素值</param>
        public Node(T t)
        {
            this.data = t;
            this.next = null;
            this.prev = null;
        }
        /// <summary>
        /// 构造方法:数据为t,下一个节点为node
        /// </summary>
        /// <param name="t">传入的元素值</param>
        /// <param name="next">上一个节点</param>
        /// <param name="prev">下一个节点</param>
        public Node(T t, Node<T> next,Node<T> prev)
        {
            this.data = t;
            this.next = next;
            this.prev = prev;
        }


        /// <summary>
        /// 此方法在调试过程中使用,可以删掉
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            T p = this.prev == null ? default(T) : this.prev.data;
            T n = this.next == null ? default(T) : this.next.data;
            string s = string.Format("Data:{0},Prev:{1},Next:{2}",data,p,n);
            return s;
        }
    }
    /// <summary>
    /// 双向链表接口
    /// </summary>
    /// <typeparam name="T">链表中元素的类型</typeparam>
    public interface ILinkList<T>
    {
        void AddFirst(T t);
        void AddLast(T t);
        void Clear();
        int Count { get; }
        Node<T> Head { get; set; }
        Node<T> Tail { get;set;}
        void Insert(int index, T t);
        bool IsEmpty { get; }
        void RemoveAt(int index);
        void RemoveFirst();
        void RemoveLast();
        Node<T> this[int index] { get; }
    }




    /// <summary>
    /// 双向链表操作类
    /// </summary>
    /// <typeparam name="T">链表中元素的类型</typeparam>
    public class LinkList<T> : ILinkList<T>
    {
        /// <summary>
        /// 链表头节点
        /// </summary>
        Node<T> head;
        /// <summary>
        /// 链表头节点
        /// </summary>
        public Node<T> Head
        {
            get { return head; }
            set { head = value; }
        }
        /// <summary>
        /// 链表尾节点
        /// </summary>
        Node<T> tail;
        /// <summary>
        /// 链表尾节点
        /// </summary>
        public Node<T> Tail
        {
            get { return tail; }
            set { tail = value; }
        }
        /// <summary>
        /// 链表大小
        /// </summary>
        int size = 0;


        /// <summary>
        /// 添加节点到链表的开头
        /// </summary>
        /// <param name="t">要添加的数据</param>
        public void AddFirst(T t)
        {
            Node<T> node = new Node<T>(t);
            //如果头为null
            if (head == null)
            {
                //把头节点设置为node
                head = node;
                //因为是空链表,所以头尾一致
                tail = node;
                //大小加一
                size++;
                return;
            }
            //原来头节点的上一个为新节点
            head.Prev = node;
            //新节点的下一个为原来的头节点
            node.Next = head;
            //新头节点为新节点
            head = node;
            //大小加一
            size++;
        }


        /// <summary>
        /// 添加节点到链表的末尾
        /// </summary>
        /// <param name="t">要添加的数据</param>
        public void AddLast(T t)
        {
            Node<T> node = new Node<T>(t);
            //如果头为null
            if (head == null)
            {
                //把头节点设置为node
                head = node;
                //因为是空链表,所以头尾一致
                tail = node;
                //大小加一
                size++;
                return;
            }
            //将原尾节点的下一个设置为新节点
            tail.Next = node;
            //将新节点的上一个设置为原尾节点
            node.Prev = tail;
            //将尾节点重新设置为新节点
            tail = node;
            //大小加一
            size++;
        }
        /// <summary>
        /// 在给定的索引处插入数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="t">要插入的数据</param>
        public void Insert(int index, T t)
        {
            Node<T> node = new Node<T>(t);
            //索引过小
            if (index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            //索引过大
            if (index >= Count)
            {
                throw new IndexOutOfRangeException();
            }
            //如果链表是空的,而且索引大于0
            if (IsEmpty && index > 0)
            {
                throw new IndexOutOfRangeException();
            }
            //如果索引为0,意味着向链表头部添加节点。
            if (index == 0)
            {
                AddFirst(t);
                return;
            }
            //要插入位置的节点
            Node<T> current = head;
            int i = 0;
            while (true)
            {
                if (i == index)
                {
                    break;
                }
                i++;
                current = current.Next;
            }
            //此处非常重要,特别要注意先后次序
            //当前节点的上一个的下一个设置为新节点
            current.Prev.Next = node;
            //新节点的上一个设置为当前节点的上一个
            node.Prev = current.Prev;
            //新节点的下一个设置为当前节点
            node.Next = current;
            //当前节点的上一个设置为新节点
            current.Prev = node;
            //大小加一
            size++;
        }
        /// <summary>
        /// 移除链表中的节点
        /// </summary>
        /// <param name="index">要移除的节点的索引</param>
        public void RemoveAt(int index)
        {
            //链表头节点是空的
            if (IsEmpty)
            {
                throw new Exception("链表是空的。");
            }
            //索引过小
            if (index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            //索引过大
            if (index >= Count)
            {
                throw new IndexOutOfRangeException();
            }
            //如果要移除的是头节点
            if (index == 0)
            {
                RemoveFirst();
                return;
            }
            if (index==size-1)
            {
                RemoveLast();
                return;
            }
            //要移除的节点
            Node<T> current = head;
            int i = 0;
            while (true)
            {
                if (i == index)
                {
                    break;
                }
                i++;
                current = current.Next;
            }
            //当前节点的上一个的Next设置为当前节点的Next
            current.Prev.Next = current.Next;
            //当前节点的下一个的Prev设置为当前节点的Prev
            current.Next.Prev = current.Prev;
            //大小减一
            size--;
        }
        /// <summary>
        /// 移除头节点
        /// </summary>
        public void RemoveFirst()
        {
            //链表头节点是空的
            if (IsEmpty)
            {
                throw new Exception("链表是空的。");
            }
            //如果size为1,那就是清空链表。
            if (size==1)
            {
                Clear();
                return;
            }
            //将头节点设为原头结点的下一个节点,就是下一个节点上移
            head = head.Next;
            //处理上一步遗留问题,原来的第二个节点的上一个是头结点,现在第二个要变成头节点,那要把它的Prev设为null才能成为头节点
            head.Prev = null;
            //大小减一
            size--;
        }
        /// <summary>
        /// 移除尾节点
        /// </summary>
        public void RemoveLast()
        {
            //链表头节点是空的
            if (IsEmpty)
            {
                throw new Exception("链表是空的。");
            }
            //如果size为1,那就是清空链表。
            if (size == 1)
            {
                Clear();
                return;
            }
            //尾节点设置为倒数第二个节点
            tail = tail.Prev;
            //将新尾节点的Next设为null,表示它是新的尾节点
            tail.Next = null;
            //大小减一
            size--;
        }
        /// <summary>
        /// 判断链表是否是空的
        /// </summary>
        public bool IsEmpty
        {
            get
            {
                return head == null;
            }
        }
        /// <summary>
        /// 链表中元素的个数
        /// </summary>
        public int Count
        {
            get
            {
                ////也可以采用遍历的方法获得长度,遍历可以从前向后,也可以从后向前
                //int count = 0;
                ////取得链表头部节点
                //Node<T> current = new Node<T>();
                //current = head;
                ////遍历整个链表,直到最后一个Next为null的节点为止
                //while (current!=null)
                //{
                //    count++;
                //    current = current.Next;
                //}
                //return count;
                return size;
            }
        }
        /// <summary>
        /// 清除链表中的数据
        /// </summary>
        public void Clear()
        {
            head = null;
            tail = null;
            size = 0;
        }
        /// <summary>
        /// 根据索引获取链表中的节点
        /// </summary>
        /// <param name="index">整型索引</param>
        /// <returns>节点</returns>
        public Node<T> this[int index]
        {
            get
            {
                //链表头节点是空的
                if (head == null)
                {
                    throw new Exception("链表是空的。");
                }
                //索引过小
                if (index < 0)
                {
                    throw new IndexOutOfRangeException();
                }
                //索引过大
                if (index >= Count)
                {
                    throw new IndexOutOfRangeException();
                }
                //取得头节点
                Node<T> current = new Node<T>();
                //如果索引在前一半,那么从前向后找
                if (index<size/2)
                {
                    current = head;
                    int i = 0;
                    //遍历链表
                    while (true)
                    {
                        //找到第index个节点
                        if (i == index)
                        {
                            break;
                        }
                        current = current.Next;
                        i++;
                    }
                    return current;
                }
                else//如果索引在后一半,那么从后向前找
                {
                    current = tail;
                    int i = size;
                    //遍历链表
                    while (true)
                    {
                        //找到第index个节点
                        if (i == index)
                        {
                            break;
                        }
                        current = current.Prev;
                        i--;
                    }
                    return current.Next;
                }
            }
        }
    }
分享到:
评论

相关推荐

    infor:数字化转型助力制造企业蜕变.pdf

    infor:数字化转型助力制造企业蜕变.pdf

    毕业论文-电视TV_新增蓝光-整站商业源码.zip

    毕业论文-电视TV_新增蓝光-整站商业源码.zip

    InTouch触摸式考勤终端介绍.PDF

    InTouch触摸式考勤终端介绍.PDF

    毕业论文-日主题子主题-整站商业源码.zip

    毕业论文-日主题子主题-整站商业源码.zip

    毕业论文-彩虹目录列表程序v1.3源码-整站商业源码.zip

    毕业论文-彩虹目录列表程序v1.3源码-整站商业源码.zip

    灭火器识别数据集,识别率99.5%,分别率640x640,127张训练图,支持pasical voc xml格式的标注框

    灭火器识别数据集,识别率99.5%,分别率640x640,127张训练图,支持pasical voc xml格式的标注框

    【Java毕业设计】勤无忧考勤工具 - 论文、源码、PPT,打造毕业作品.zip

    此压缩包包含了本毕业设计项目的完整内容,具体包括源代码、毕业论文以及演示PPT模板。 开发语言:Java 框架:SSM(Spring、Spring MVC、MyBatis) JDK版本:JDK 1.8 或以上 开发工具:Eclipse 或 IntelliJ IDEA Maven版本:Maven 3.3 或以上 数据库:MySQL 5.7 或以上 项目配置完成后即可运行,若需添加额外功能,可根据需求自行扩展。 运行条件 确保已安装 JDK 1.8 或更高版本,并正确配置 Java 环境变量。 使用 Eclipse 或 IntelliJ IDEA 打开项目,导入 Maven 依赖,确保依赖包下载完成。 配置数据库环境,确保 MySQL 服务正常运行,并导入项目中提供的数据库脚本。 在 IDE 中启动项目,确认所有服务正常运行。 主要功能简述: 请假审批流程:系统支持请假申请的逐级审批,包括班主任审批和院系领导审批(针对超过三天的请假)。学生可以随时查看请假申请的审批进展情况。 请假记录管理:系统记录学生的所有请假记录,包括请假时间、原因、审批状态及审批意见等,供学生和审批人员查询。 学生在线请假:学生可以通过系统在线填写请假申请,包括请假的起止日期和请假原因,并提交给班主任审批。超过三天的请假需经班主任审批后,再由院系领导审批。 出勤信息记录:任课老师可以在线记录学生的上课出勤情况,包括迟到、早退、旷课和请假等状态。 出勤信息查询:学生、任课老师、班主任、院系领导和学校领导均可根据权限查看不同范围的学生上课出勤信息。学生可以查看自己所有学年的出勤信息,任课老师可以查看所教班级的出勤信息,班主任和院系领导可以查看本班或本院系的出勤信息,学校领导可以查看全校的出勤信息。 出勤统计与分析:系统提供出勤统计功能,可以按班级、学期等条件统计学生的出勤情况,帮助管理人员了解学生的出勤状况。 用户管理:系统管理员负责管理所有用户信息,包括学生、任课老师、班主任、院系领导和学校领导的账号创建、权限分配等。 数据维护:管理员可以动态更新和维护系统所需的数据,如学生信息、课程安排、学年安排等,确保系统的正常运行。 系统配置:管理员可以对系统进行配置,如设置数据库连接参数、调整系统参数等,以满足不同的使用需求。 身份验证:系统采用用户名和密码进行身份验证,确保只有授权用户才能访问系统。不同用户类型(学生、任课老师、班主任、院系领导、学校领导、系统管理员)具有不同的操作权限。 权限控制:系统根据用户类型分配不同的操作权限,确保用户只能访问和操作其权限范围内的功能和数据。 数据安全:系统采取多种措施保障数据安全,如数据库加密、访问控制等,防止数据泄露和非法访问。

    【电子设计竞赛】具有发电功能的储能小车设计与制作:高职高专组比赛任务及要求详解

    内容概要:本文档为2021年全国大学生电子设计竞赛的试题,针对“具有发电功能的储能小车”这一主题进行了详细的任务描述、要求说明及评分标准设定。任务要求设计并制作一款以超级电容为储能元件的手动发电智能小车,通过在特定区域内往复运动完成充电,之后按照规定执行直线行驶或沿圆形轨迹行驶的动作,并具备LED指示、液晶显示行驶距离等功能。基本要求涵盖小车的充电、启动控制、行驶距离等;发挥部分则增加了循迹行驶、硬币探测等挑战性任务。文档还对竞赛规则、测试条件等做了明确说明; 适合人群:参加全国大学生电子设计竞赛的高职高专组学生; 使用场景及目标:①为参赛队伍提供具体的设计与制作指导;②确保各参赛队伍理解竞赛规则、评分标准,以便准备比赛; 阅读建议:仔细研读任务要求和评分细则,确保设计方案符合所有规定,同时关注发挥部分以争取更高分数。

    汽车BCM程序源代码解析:灯光控制、雨刮洗涤、遥控及通讯功能的实现

    内容概要:本文详细介绍了汽车BCM(车身控制模块)程序源代码的关键功能和技术细节。首先探讨了BCM对外部灯光(如前照灯、转向灯、雾灯等)和内部灯光(如顶灯、门灯等)的精确控制机制,确保驾驶员和乘客的安全与舒适。其次,阐述了BCM对前后雨刮和洗涤系统的智能控制,提升车辆在恶劣天气条件下的能见度。接着,讲解了遥控钥匙(RKE)和门锁系统的运作方式,使车主能够远程操控车辆。最后,深入分析了CAN/LIN通讯和ISO15765诊断协议的应用,确保车辆各模块之间的高效协同和故障诊断。文中还展示了部分伪代码示例,帮助读者更好地理解BCM的具体实现。 适用人群:汽车电子工程师、嵌入式软件开发者、汽车爱好者。 使用场景及目标:适用于希望深入了解汽车BCM工作原理的技术人员,旨在掌握BCM在灯光控制、雨刮洗涤、遥控及通讯等方面的具体实现方法,从而应用于实际项目开发或故障排查。 其他说明:本文不仅提供了理论知识,还附有简单代码示例,便于读者理解和实践。

    毕业论文-深蓝AI智能名片小程序1.7.1-整站商业源码.zip

    毕业论文-深蓝AI智能名片小程序1.7.1-整站商业源码.zip

    基于springboot的“考研资讯平台”的设计与实现(源码+数据库+文档+PPT).zip

    # 基于springboot的“考研资讯平台”的设计与实现(源码+数据库+文档+PPT) - 开发语言:Java - 数据库:MySQL - 技术:springboot - 工具:IDEA/Ecilpse、Navicat、Maven

    VMware 17最新安装包

    VMware 17最新安装包

    电动汽车电机控制器:基于英飞凌TC27xC平台的详细设计方案及其实现

    内容概要:本文详细介绍了一种基于英飞凌TC27xC平台的电动汽车电机控制器设计方案。该方案涵盖了原理图、Bom清单、代码及其分析。文中首先概述了方案的整体架构,接着深入解析了原理图中的关键组件,如PWM信号用于控制电机速度和方向,以及ADC用于实时监控电流和电压。随后,提供了详细的Bom清单,列出了所有必要的电子元件。代码部分则分为初始化代码、电机控制代码和代码分析,展示了模块化的编程思路,确保系统的稳定性和易维护性。最后,介绍了该方案在实际电动汽车中的成功应用,强调了其对提升驾驶体验和安全性的贡献。 适合人群:从事电动汽车研发的技术人员、硬件工程师、嵌入式软件开发人员。 使用场景及目标:适用于正在研究或开发电动汽车电机控制系统的人群,旨在帮助他们理解和实现高效的电机控制解决方案。 其他说明:本文不仅提供了理论和技术细节,还分享了实践经验,有助于读者更好地掌握相关技术和应用场景。

    java必读之代码大全笔记

    java必读之代码大全笔记

    20张人脸面部不同区域分割、有标签

    20张人脸面部不同区域分割、有标签

    Java设计成品】学生考勤监控 - 论文、源码、PPT打包.zip

    此压缩包包含了本毕业设计项目的完整内容,具体包括源代码、毕业论文以及演示PPT模板。 开发语言:Java 框架:SSM(Spring、Spring MVC、MyBatis) JDK版本:JDK 1.8 或以上 开发工具:Eclipse 或 IntelliJ IDEA Maven版本:Maven 3.3 或以上 数据库:MySQL 5.7 或以上 项目配置完成后即可运行,若需添加额外功能,可根据需求自行扩展。 运行条件 确保已安装 JDK 1.8 或更高版本,并正确配置 Java 环境变量。 使用 Eclipse 或 IntelliJ IDEA 打开项目,导入 Maven 依赖,确保依赖包下载完成。 配置数据库环境,确保 MySQL 服务正常运行,并导入项目中提供的数据库脚本。 在 IDE 中启动项目,确认所有服务正常运行。 主要功能简述: 请假审批流程:系统支持请假申请的逐级审批,包括班主任审批和院系领导审批(针对超过三天的请假)。学生可以随时查看请假申请的审批进展情况。 请假记录管理:系统记录学生的所有请假记录,包括请假时间、原因、审批状态及审批意见等,供学生和审批人员查询。 学生在线请假:学生可以通过系统在线填写请假申请,包括请假的起止日期和请假原因,并提交给班主任审批。超过三天的请假需经班主任审批后,再由院系领导审批。 出勤信息记录:任课老师可以在线记录学生的上课出勤情况,包括迟到、早退、旷课和请假等状态。 出勤信息查询:学生、任课老师、班主任、院系领导和学校领导均可根据权限查看不同范围的学生上课出勤信息。学生可以查看自己所有学年的出勤信息,任课老师可以查看所教班级的出勤信息,班主任和院系领导可以查看本班或本院系的出勤信息,学校领导可以查看全校的出勤信息。 出勤统计与分析:系统提供出勤统计功能,可以按班级、学期等条件统计学生的出勤情况,帮助管理人员了解学生的出勤状况。 用户管理:系统管理员负责管理所有用户信息,包括学生、任课老师、班主任、院系领导和学校领导的账号创建、权限分配等。 数据维护:管理员可以动态更新和维护系统所需的数据,如学生信息、课程安排、学年安排等,确保系统的正常运行。 系统配置:管理员可以对系统进行配置,如设置数据库连接参数、调整系统参数等,以满足不同的使用需求。 身份验证:系统采用用户名和密码进行身份验证,确保只有授权用户才能访问系统。不同用户类型(学生、任课老师、班主任、院系领导、学校领导、系统管理员)具有不同的操作权限。 权限控制:系统根据用户类型分配不同的操作权限,确保用户只能访问和操作其权限范围内的功能和数据。 数据安全:系统采取多种措施保障数据安全,如数据库加密、访问控制等,防止数据泄露和非法访问。

    commons-csv-1.8.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    毕业论文- 灵石人才招聘plus商用V1.4.2-整站商业源码.zip

    毕业论文- 灵石人才招聘plus商用V1.4.2-整站商业源码.zip

    sentinel-cluster-common-default-1.8.0.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    【Java设计精品】勤达勤平台 - 论文、源码、PPT一站式.zip

    开发语言:Java 框架:SSM(Spring、Spring MVC、MyBatis) JDK版本:JDK 1.8 或以上 开发工具:Eclipse 或 IntelliJ IDEA Maven版本:Maven 3.3 或以上 数据库:MySQL 5.7 或以上 此压缩包包含了本毕业设计项目的完整内容,具体包括源代码、毕业论文以及演示PPT模板。 项目配置完成后即可运行,若需添加额外功能,可根据需求自行扩展。 运行条件 确保已安装 JDK 1.8 或更高版本,并正确配置 Java 环境变量。 使用 Eclipse 或 IntelliJ IDEA 打开项目,导入 Maven 依赖,确保依赖包下载完成。 配置数据库环境,确保 MySQL 服务正常运行,并导入项目中提供的数据库脚本。 在 IDE 中启动项目,确认所有服务正常运行。 主要功能简述: 用户管理:系统管理员负责管理所有用户信息,包括学生、任课老师、班主任、院系领导和学校领导的账号创建、权限分配等。 数据维护:管理员可以动态更新和维护系统所需的数据,如学生信息、课程安排、学年安排等,确保系统的正常运行。 系统配置:管理员可以对系统进行配置,如设置数据库连接参数、调整系统参数等,以满足不同的使用需求。 身份验证:系统采用用户名和密码进行身份验证,确保只有授权用户才能访问系统。不同用户类型(学生、任课老师、班主任、院系领导、学校领导、系统管理员)具有不同的操作权限。 权限控制:系统根据用户类型分配不同的操作权限,确保用户只能访问和操作其权限范围内的功能和数据。 数据安全:系统采取多种措施保障数据安全,如数据库加密、访问控制等,防止数据泄露和非法访问。 请假审批流程:系统支持请假申请的逐级审批,包括班主任审批和院系领导审批(针对超过三天的请假)。学生可以随时查看请假申请的审批进展情况。 请假记录管理:系统记录学生的所有请假记录,包括请假时间、原因、审批状态及审批意见等,供学生和审批人员查询。 学生在线请假:学生可以通过系统在线填写请假申请,包括请假的起止日期和请假原因,并提交给班主任审批。超过三天的请假需经班主任审批后,再由院系领导审批。 出勤信息记录:任课老师可以在线记录学生的上课出勤情况,包括迟到、早退、旷课和请假等状态。 出勤信息查询:学生、任课老师、班主任、院系领导和学校领导均可根据权限查看不同范围的学生上课出勤信息。学生可以查看自己所有学年的出勤信息,任课老师可以查看所教班级的出勤信息,班主任和院系领导可以查看本班或本院系的出勤信息,学校领导可以查看全校的出勤信息。 出勤统计与分析:系统提供出勤统计功能,可以按班级、学期等条件统计学生的出勤情况,帮助管理人员了解学生的出勤状况

Global site tag (gtag.js) - Google Analytics