package 链表; /* * 链表是一种常见的数据结构,不同于数组有固定的长度,它是动态进行存储分配的一种结构。 * 例如一个班级有50人,但是另外一个班级只有40人,如果用数组存储它们需要定义一个长度 * 为50的数组,而其他班级并没有这么多人,这将会浪费许多的存储空间。 * 每个链表都有一个头指针,指向第一个节点。通常每个节点分为两个部分,用户存放的数据 * 和指向下一个节点的地址。每个节点依次向下指向,最后一个指向一个NULL表示链表结束。 * 在操作链表时,头指针一般不动(方便遍历所有链表数据),通常重新定义一个新的指针与 * 头指针指向相同地址,来进行数据操作。 * C语言创建链表主要代码: * struct student * { * int data; * struct student *next; * } * void main() * { * struct student *head; * struct student *p1,*p2; * int n=0; * p1=p2=(struct student*)malloc(sizeof(struct student)); * scanf("%d",&p1->data); * head=NULL; * while(p1->data!=0) * { * n++; * if(n==1) * { * head=p1; * }else{ * p2->next=p1; * } * p2 = p1; * p1=(struct student*)malloc(sizeof(struct student)); * scanf("%d",&p1->data); * } * p2->next=NULL; * } * 从上述C语言创建链表可见流程较为繁琐,数据分布在内存任意位置,通过指针指向下一个地 * 址来关联,所以在查找数据时链表没有数组直观且效率高,但是链表在进行增加、删除、插入时效 * 率比数组要好,因为链表只需要改变指针指向就可以达到增加、删除、插入效果,而数组则需要重 * 新给它们的位置排序效率低。 * 下面代码使用Java语言编写的链表,不同于C语言,Java没有指针概念,而是通过节点的引 * 用与下一个节点产生联系。创建了一个双向链表,可以向下遍历,同时可以向上遍历,且实现了链 * 表的增、删、改、查操作。(上课时老师编写的代码并没有完全实现双向链表增、删、改、查等功 * 能,我已经将代码完善。) */ public class MyLinkList<E> { private Node <E> head = null;//头节点 private Node <E> last = null;//尾节点 private int num = 0;//节点个数 public MyLinkList(){} public void add(E e){//增加链表节点 Node<E> node = new Node<E>(e);//创建一个新的节点 if(last != null)//如果尾节点last不等于空,则向后添加新的节点。 { last.next = node; node.front = last; last = node;//尾节点last向后移动 last.next = null;//且尾节点last下一个等于空,表示链表结束 } else {//如果尾节点last等于空,说明这是第一个节点,需要把新节点node定义为头、尾节点 head = node; head.front = null;//头节点head上一个为空 last = node; } num++;//节点个数加1 } public void intsert(int index,E e)//在链表第index个位置插入节点 { Node<E> node = new Node<E>(e); Node<E> n1 = getMode(index);//通过getMode方法返回第index个节点 if(index == 0){//index等于0是头节点 node.next = n1; node.front = null; head = node; n1.front = node; }else if(index == num-1){//index等于num-1是尾节点 Node<E> n2 = n1.front; n2.next = node; node.front = n2; node.next = n1; n1.front = node; last = n1; last.next = null; }else{ Node<E> n2 = n1.front; n2.next = node; node.front = n2; node.next = n1; n1.front = node; } num++; } public void delete(int index){//删除第index个节点 if(index >= 0 && index <num){ if(index==0){ head=head.next; head.front = null; }else if(index==num-1){ last = last.front; last.next =null; }else{ Node<E> n1 = getMode(index); Node<E> n2 = n1.front; n2.next=n1.next; n2 = n1.next.front; } num--; }else{ throw new IndexOutOfBoundsException("下标超出范围:index"+index+",size"+num); } } public void delete(E e){//删除链表中的某个数据的节点 int index = First(e);//获得第一个节点的位置 delete(index); } public void update(int index,E e){//更新第index个的数据 Node<E> node = getMode(index); node.data = e; } public int First(E e)//查找第一个符合要求的位置 { Node<E> node = head; int index=-1; while (node != null) { index++; if(node.data.equals(e)){ break; } node=node.next; } return index; } public int Last(E e)//查找最后一个符合要求的位置 { Node<E> node = last; int index=num; while (node != null) { index--; if(node.data.equals(e)){ break; } node=node.front; } return index; } public E get(int index){//正向获取第index个节点的数据 Node<E> node = getMode(index); return node.data; } public E getlast(int index){//反向获取第index个节点的数据 Node<E> node = getlastMode(index); return node.data; } private Node<E> getMode(int index){//正向获取第index个节点的数据的具体方法 int t = -1; if(index >= 0 && index <num){ Node<E> n = head; while(n != null) { t++; if(t == index){ break; } n=n.next; } return n; }else { throw new IndexOutOfBoundsException("下标超出范围:index"+index+",size"+num); } } private Node<E> getlastMode(int index){//反向获取第index个节点的数据的具体方法 int t = num; if(index >= 0 && index <num){ Node<E> n = last; while(n != null) { t--; if(t == index){ break; } n=n.front; } return n; }else { throw new IndexOutOfBoundsException("下标超出范围:index"+index+",size"+num); } } public void HeadInquire()//从头开始遍历链表 { Node<E> node = new Node<E>(); node = head; while(node != null){ System.out.println(node.data); node = node.next; } } public void LastInquire()//从尾开始遍历链表 { Node<E> node = new Node<E>(); node = last; while(node != null){ System.out.println(node.data); node = node.front; } } public int size(){//获取节点个数 return num; } } class Node<E>{ E data; Node<E> next;// 对下一个节点的引用 Node<E> front;// 对前一个节点的引用 public Node(){ } public Node(E e){ this.data = e; } }
package 链表; public class Main { public static void main(String[] args) { // TODO Auto-generated constructor stub MyLinkList<String> node = new MyLinkList<String>(); for(Character i=65;i<70;i++){ node.add(i.toString());//增加链表节点 } // node.intsert(0, "HH");//插入几点 // node.delete(4);//根据节点位置删除节点 // node.delete("A");//根据内容删除符合要求的第一个节点 // node.update(1, "E");//通过节点位置更新内容 // System.out.println(node.First("E"));//查找第一个符合要求的位置 // System.out.println(node.Last("E"));//查找最后一个符合要求的位置 // for(int i=0;i<node.size();i++){//通过链表节点个数正向遍历链表 // String s=node.get(i); // System.out.println(s); // } // for(int i=node.size()-1;i>=0;i--){//通过链表节点个数反向遍历链表 // String s=node.getlast(i); // System.out.println(s); // } node.HeadInquire();//通过链表是否为空正向遍历链表 // node.LastInquire();//通过链表是否为空正向遍历链表 } }
相关推荐
本文将详细探讨如何实现双向链表的增、删、改、查操作,并通过C++编程语言的DLink.cpp文件进行实际应用。 首先,我们需要定义双向链表的节点结构。一个双向链表节点包含两个指针,分别指向其前一个节点和后一个节点...
链表的主要类型包括单向链表、双向链表和循环链表等。 ### 二、代码解析 #### 1. 结构体定义 ```c struct Student { char name[12]; char sno[12]; int score; Student* next; }; ``` 这里定义了一个名为`...
接下来,我们来看如何实现增删改查操作: 1. **增加(Add)**:在链表中插入新的航空信息,我们需要创建一个新的节点,填充相关信息,然后将新节点插入到合适的位置。由于是双向循环链表,我们需要同时更新前后节点...
线性表的增删改查操作 - **插入**:在线性表的指定位置插入一个新元素,需要找到插入点并更新指针。对于链表,这涉及修改前后两个节点的指针。 - **删除**:根据给定的元素或位置删除一个元素,需要找到要删除的...
本主题聚焦于C语言实现的单双向链表,包括链表的基本操作:增、删、改、查和排序。以下是这些核心知识点的详细说明。 首先,链表是一种动态数据结构,它不像数组那样在内存中连续存储元素,而是通过节点间的指针...
以下是一个简单的C语言实现双向链表的代码示例,包括创建节点、在链表尾部添加节点、在链表头部添加节点、删除节点、修改节点等功能: ```c #include #include typedef struct Node { int data; struct Node* ...
这个项目"单链表c语言实现增删改查操作"是基于VS2008运行环境,用C语言编程实现对单链表的基本操作,包括插入、删除、修改和查询元素,并将结果输出到控制台。 首先,我们需要定义链表的节点结构: ```c typedef ...
本资料包提供了一套完整的C语言数据结构库,特别关注于队列、栈、链表和树这四种基本数据结构的增删改查操作。 1. 队列:队列是一种先进先出(FIFO)的数据结构,类似于现实生活中的排队。在这个库中,你可以找到...
以上就是关于双向链表的增删改查和排序的C++实现。双向链表的灵活性使其在处理需要双向遍历或频繁插入、删除操作的问题时特别有用。通过这个实现,我们可以高效地处理链表数据,进行各种操作,并能根据需求对其进行...
对于初学者来说,理解如何在List中进行增删改查操作是掌握Java集合框架的基础。本文将详细介绍这些基本操作。 1. **添加元素(Add)** - `add()` 方法:向列表末尾添加一个元素,如 `list.add(element)`。 - `add...
在本项目中,我们将深入探讨如何使用MFC创建一个功能完备的通讯录应用,该应用能够进行联系人的增删改查、存储和读取操作,适用于大学生课程设计作业。虽然该项目尚不支持动态添加联系人头像,但其核心功能已经足够...
此外,为了实现图形用户界面(GUI),可能需要利用C++库,如Qt或wxWidgets,它们提供了一系列用于创建窗口、按钮、文本框等元素的类,使用户可以通过点击按钮执行增删改查操作。 最后,为了保证程序的健壮性和用户...
在C++中,我们可以自定义结构体或类来表示链表节点,并通过指针操作实现各种操作,如增、删、改、查。 首先,我们来看双向链表的基本节点结构。在C++中,通常定义一个名为`Node`的结构体或类,它包含三个部分:存储...
在本压缩包中,我们重点关注了三种类型的线性表:顺序表、链表和双链表,以及它们的增删查改操作和链表逆置等常见算法。 顺序表是一种最简单的线性表实现,它在内存中是连续存储的,可以通过数组来表示。对于顺序表...
本文将深入探讨如何使用C语言来实现单向链表,并扩展到实现双向链表的“增删改查显”功能。 首先,让我们了解链表的基本概念。链表是一种线性数据结构,与数组不同,它在内存中不是连续存储的。每个链表节点包含两...
双向链表允许节点在链表中的前向和后向移动,这使得插入和删除操作相对快速,尤其适合频繁进行增删操作的场景,如航班信息的动态管理。每个链表节点包含航班的相关信息,如航班号、起降时间、航线、飞机型号等。 该...
用户可能需要通过输入命令来执行增删改查等操作。 通过这个项目,初学者不仅能深入理解双向链表的工作原理,还能学习如何在实际编程环境中应用这些知识,包括文件I/O操作(保存和加载学生信息到磁盘)、错误处理和...
在这个主题中,我们将深入探讨"单链表"这种基本的数据结构以及在C语言中如何进行增删改查的操作。 单链表是一种线性数据结构,其中的元素(节点)通过指向下一个元素的指针连接在一起。每个节点包含两部分:数据域...
5. **数据容器**:这可能是指一个通用的数据结构,用于存储和操作各种类型的数据,可以使用链表作为基础,提供多种操作接口,如增删改查。 在VB6中实现这些数据结构时,需要注意错误处理、内存管理(如释放不再使用...
- 通过查看源码,可以学习到如何在VC++环境中创建和管理链表,理解链表操作的具体实现。 - 演示部分有助于理解动态数据结构的概念,提升对链表操作的实际应用能力。 - Timer事件的结合使用,为可视化编程提供了...