链表主要分为单向链表、双向链表、循环链表
双向链表、循环链表都可以认为是单向链表的扩展,单向链表最基础,笔者的介绍也将基于单向列表
单向链表是一个在物理存储上不相邻的序列(与数组不同),它由结点组成,每个结点分为指针域和值域,值域发挥与数组元素类似的存储数值的作用,而指针域存储下一个结点的地址,结点与结点之间通过指针相连。
下图是单向链表的逻辑结构
可见只要得到第一个元素(通常称为头结点)即可通过指针获取整个链表的元素。
定义一个结点类
public class Node {
//值域,定义为Object,能够存储任意类型的值
Object obj;
//指针域
Node next;
public Node(Object obj){
this.obj=obj;
}
}
定义一个链表类
public class LinkedList{
//指向第一个元素的头结点
Node head=null;
//指向最后一个元素的尾结点
Node last=head;
}
以下代码均为LinkedList类中的方法
添加元素
public void add(Object obj){
Node node=new Node(obj);
//将每个结点添加到尾结点后面,如果链表尚未添加任何元素
//则将要添加的结点赋给头结点,之后让last指向最后一个结点
if(head!=null){
last.next=node;
}else{
head=node;
}
last=node;
}
获取链表的元素个数
public int size(){
int count=0;
Node node=head;
while(node!=null){
count++;
node=node.next;
}
return count;
}
获取指定位置的元素
public Node get(int index){
int count=0;
Node node=head;
while(node!=null){
if(index==count){
return node;
}else{
node=node.next;
count++;
}
}
return null;
}
给链表排序的方法
public void sort(int sequence){
Node p,q,r;
//sequence判断按升序还是降序排列,此处为升序
if(sequence==0){
for(int i=size();i>1;i--){
for(int j=0;j<i-1;j++){
if(Integer.parseInt(get(j).obj.toString())>Integer.parseInt(get(j+1).obj.toString())){
//如果相邻的两个结点,前一个结点(赋给q)的值大于后一个结点(赋给r),则将他们的结点交换
q=get(j);r=get(j+1);
//让q的指针指向r的下一个元素
q.next=r.next;
//让r的指针指向q
r.next=q;
//让指向q的元素指向r
if(j!=0){
get(j-1).next=r;
}
//如果q为第一个元素,则交换后的r为第一个元素,将其赋给头结点
if(j==0){
head=r;
}
if(q.next==null){
last=q;
}
}
}
}
}
//此方法仅考虑了按升序排列的情况,如果按降序排列,仅需将判断语句if()中的>改为<
}
让链表转置的方法
public void reverse(){
Node node_temp;
//让后一个结点的指针指向前一个结点
for(int i=size()-2;i>=0;i--){
get(i+1).next=get(i);
}
//原本的头结点此时为最后一个元素,即尾结点
head.next=null;
node_temp=head;
//原本的尾结点此时为头结点
head=last;
last=node_temp;
}
}
判断链表是否有环的方法
/**如果链表中的尾结点的指针并不为空,而是指向某个结点(包括它本身),则认为此链表有环*/
public static boolean isCircle(Node head){
Node n1,n2;
n1=n2=head;
/**两个元素n1、n2从头结点开始读取整个链表
* 一个按顺序读,另一个间隔一个元素读,如果链表有环
* 则一定会有n1=n2的情况
*/
while(n1!=null&&n2!=null){
try{
n1=n1.next;
n2=n2.next.next;
if(n1.equals(n2)){
return true;
}
}catch(NullPointerException e){
//如果n1 n2某次读到了空值,则该链表一定无环
return false;
}
}
return false;
}
以上代码存在一定缺陷
譬如调用get(int index)须每次从头结点开始读取,在排序方法中多次使用get(int index)方法可能造成时间的浪费。
- 描述: 单向链表的逻辑结构图
- 大小: 16.4 KB
分享到:
相关推荐
本教程将通过两个经典示例深入讲解如何在C语言中使用链表。 首先,我们来看第一个示例——"Demo1.c"。在这个示例中,我们将创建一个表示学生成绩的链表,每个节点包含学生的ID和分数。为了实现这个链表,我们需要...
总结来说,这个C++链表教程涵盖了链表的基本概念、数据结构定义、操作符重载以及常见的链表操作函数实现,这些都是理解和使用链表的关键知识。通过这些内容,开发者可以有效地在C++中构建和管理链表数据结构,进行...
双向链表使用说明.txt
使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现...
数据结构学习辅助,链表使用例程,注释非常清楚,而且可以实际运行,方便初学者调试、体会
将linux内核源码中list.h拿出来, 增删与遍历部分写了详细注释, 关于链表合并, 没用过所以没写. 源码版本是2.6.32, 不过链表的源码改动应该不是很大. 我的邮箱2253238252@qq.com, 代码有什么不对的欢迎发邮件给我
在本文中,我们将深入探讨如何使用C++实现双向循环链表。双向循环链表是一种特殊的数据结构,每个节点不仅包含数据,还包含两个指针,分别指向前一个节点和后一个节点,形成一个首尾相接的循环链。这种数据结构在...
链表使用引用来定位元素,时间复杂度为O(n)。这也就是为什么数组的访问速度比链表快的原因。 5. 插入和删除操作 数组插入或删除元素的时间复杂度为O(n),因为需要移动所有元素的位置。链表插入或删除元素的时间...
链表使用指针来指向下一个节点,这可以导致指针的使用不当。 ### 实现的复杂性 链表的实现可以很复杂,需要考虑节点的管理、内存的分配等问题。 数组与链表的对比 ------------------- 数组和链表是两种常用的...
3. 节点号排序:这通常涉及到对链表的遍历,可以使用各种排序算法,如冒泡排序、选择排序或更高效的快速排序、归并排序等。在这个实例中,可能根据图书的编号进行排序。 4. 节点搜索:查找链表中特定值的节点,通常...
这些扩展都是基于基础的`list`结构,增加了链表使用的灵活性和效率。 在实际应用中,比如在网络过滤框架Netfilter中,使用链表来组织协议族的`nf_sockopt_ops`结构,每个结构都有一个`struct list_head list`成员,...
- **链表的动态内存管理**:链表使用`malloc`动态分配内存,当链表不再需要时,应使用`free`释放已分配的内存,防止内存泄漏。 - **异常处理**:在实际编程中,应添加输入验证和错误处理机制,确保输入的有效性和...
在实际开发中,为了提高效率,可以考虑使用哈希表或二叉搜索树等数据结构配合链表使用。例如,可以建立一个哈希表,键为学号,值为指向链表中对应节点的指针,这样可以在常数时间内完成查找和删除操作。 链表在人工...
动态链表使用完毕后,需要释放每个节点占用的内存空间,避免内存泄漏。 ```c void freeList(struct Car *head) { struct Car *p = head; while (p != NULL) { struct Car *temp = p; p = p->next; free...
数组和链表的使用场景 在计算机科学中,数组和链表是两种基本的数据结构,它们都是线性表的实现方式,但它们有着不同的存储结构和访问方式,从而导致不同的使用场景。 数组是一种连续存储的数据结构,即在内存中...
在这个课程设计中,我们将探讨如何使用链表来实现信息管理,包括增加、删除和显示链表中的节点。 链表的基本概念: 链表不同于数组,它不是在内存中连续分配空间,而是由一系列分散的节点组成,每个节点包含数据和...
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:...
对于初学者来说,这是一份很好的学习资料,能够帮助他们理解链表的工作原理,以及如何在实际编程中使用链表。通过阅读和分析代码,可以加深对链表数据结构的理解,并掌握其在不同场景下的应用。同时,还可以学习如何...
封装了链表的操作,功能有链表的创建,节点的添加(附加),插入(前插、后插和插入到链表头部),删除,得到节点数据,得到节点位置,得到节点总数,释放链表。 使用了类模版,使得可以让节点中的数据为任意类型,...