数据结构之单链表实现(JAVA语言+C语言)

news2024/11/26 13:52:46

一、理论

1 单链表结构

在这里插入图片描述

2 增、删、查 、改思路

  • (增)直接添加放到最后即可。按顺序添加:找到要修改的节点的前一个节点,插入新节点()。
  • (改)要修改的节点修改内容即可。
  • (删)找到待删除节点的前一个节点,把要删除节点的后一个节点信息存放到该节点的next即可
  • (查==较容易)遍历依次打印即可。按编号查找,找到对应编号打印即可

二、代码实现

1、1JAVA代码实现

package basicdata;

public class SingleLinkedListTest {
    public static void main(String[] args) {
        Node node1 = new Node(123, "Tom", "无极剑道");
        //

        SingleLinkedList singleLinkedList = new SingleLinkedList();
        singleLinkedList.addNode(node1);
        singleLinkedList.list();
        System.out.println("*******************");
        singleLinkedList.addByOrder(new Node(234, "Jack", "断头斩杀"));
        singleLinkedList.addByOrder(new Node(121, "Jack", "断头斩杀"));
        singleLinkedList.addByOrder(new Node(121, "Jack", "断头斩杀"));
        singleLinkedList.list();
        //System.out.println("******修改后*******");
        //singleLinkedList.alter(new Node(121, "Bob", "无形之刃"));
        //singleLinkedList.list();
       // System.out.println("**************");
        //singleLinkedList.delNode(234);

        System.out.println("***反转后***");
        singleLinkedList.reverSetList();
        singleLinkedList.list();

    }
}
//
class SingleLinkedList{
    // 先初始化一个头结点,头节点不存放数据
    private Node head = new Node(0,"表头","领导单链表");

    // 返回表头
    public Node getHead(){
        return head;
    }

    public SingleLinkedList() {
    }

    // 添加节点到单链表,按添加顺序排列
    public void addNode(Node node){

        // 思路:把头结点的地址给temp
        //      直到next = null时,让next存放添加的节点

        Node temp = head;
        while (true){
            if (temp.next == null) {
                break;
            }
            else {
                temp = temp.next;

            }
        }
        // 退出while 循环时 temp.next = null
        temp.next  = node;
    }

    // 遍历单链表
    public void list(){
        Node temp = head;
        if (head == null) {
            System.out.println("链表为空");
            return;
        }
        while (true){
            if (temp == null) {
                break;
            }
            else {
                // 输出节点信息
                System.out.println(temp);
                // 指针后移
                temp = temp.next;
            }
        }
    }

    //  根据编号顺序插入节点 ,链表内容按编号从小到大排列
    public void addByOrder(Node node){
        // 需要先找到要添加位置的前一个节点

        // 链表为空不需要单独考虑
        Node temp = head;
        // 为找到插入位置 需要一个 flag
        boolean flag = false;
        while (true){
            // 此情况可以添加,添加到表头后
            if (temp.next == null) { // 到链表末端
                break;
            }
            // 此情况不可以添加,要添加的编号已经存在
            if (temp.next.number == node.number) {
                flag = true;
                break;
            }
            //此情况为找到要添加位置的前一个节点,可以添加
            if (temp.next.number > node.number) {
                break;
            }
            else {
                temp = temp.next;
            }
        }

        if (flag ) {
            System.out.printf("你要插入的节编号%d已经存在",node.number);
            System.out.println();
        }
        else {
            node.next = temp.next ;
            temp.next=node;
        }
    }
    // 修改节点信息(根据编号),编号不变,修改内容
    public void alter(Node node){
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }

        // 和按编号插入(Node temp = head;)稍微有点区别
        // Node temp  = head.next;
        Node temp  = head.next;
        boolean flag = false;
         while (true){
             if (temp == null) {
                 break;
             }
             // 找到要修改的节点,可以修改
             if (temp.number == node.number) {
                 flag = true;
                 break;
             }
             else {
                 temp = temp.next;
             }
         }
        if (flag) {
            // 修改
            temp.name = node.name;
            temp.skill= node.skill;
        }
        else {
            System.out.println("没有找到要修改的节点");
        }

    }
    // 根据编号删除节点
    public void delNode(int number){
        //需要找到待删除的前一个节点
        Node temp = head;
        boolean flag = false;
        while (true){
            if (temp.next == null) {
                break;
            }
            //找到待删除的前一个节点
            if (temp.next.number == number) {
                flag = true;
                break;
            }
            else {
                temp  =  temp.next;
            }

        }
        if (flag ) {
            //
            temp.next = temp.next.next;
        }
        else {
            System.out.println("要删除的元素不存在");
        }
    }

    // 反转单链表
    public void reverSetList(){
        if (this.head.next== null||this.head.next.next==null) {
            return;
        }

        Node tempCur = this.head.next; // 辅助变量
        Node tempNext = null;      // 指向tempCur,不然会丢失
        Node reverSetHead = new Node(0, "", ""); // 新链表
        while (tempCur != null){
            tempNext = tempCur.next; //存储当前节点的下一节点
            tempCur.next = reverSetHead.next;// 头插法 把当前节点接到到reverSetHead
            reverSetHead.next = tempNext;
            tempCur=tempNext;// 后移
        }
        this.head.next = reverSetHead.next;
    }

}
// 定义Node
class Node{
    public int number;
    public String name;
    public String skill;
    public Node next;    //存放下一个节点地址
//构造器
    public Node(int number, String name, String skill) {
        this.number = number;
        this.name = name;
        this.skill = skill;

        //this.next = next;
        // 理解:不给next赋值
        //没申请一个节点时 next = null
    }
    //重写 toString
    @Override
    public String toString() {
        return "Node{" +
                "number=" + number +
                ", name='" + name + '\'' +
                ", skill='" + skill + '\'' +
                '}';
    }
}

1.2运行结果

Node{number=0, name='表头', skill='领导单链表'}
Node{number=123, name='Tom', skill='无极剑道'}
*******************
你要插入的节编号121已经存在
Node{number=0, name='表头', skill='领导单链表'}
Node{number=121, name='Jack', skill='断头斩杀'}
Node{number=123, name='Tom', skill='无极剑道'}
Node{number=234, name='Jack', skill='断头斩杀'}
******修改后*******
Node{number=0, name='表头', skill='领导单链表'}
Node{number=121, name='Bob', skill='无形之刃'}
Node{number=123, name='Tom', skill='无极剑道'}
Node{number=234, name='Jack', skill='断头斩杀'}
删除后**************
Node{number=0, name='表头', skill='领导单链表'}
Node{number=121, name='Bob', skill='无形之刃'}
Node{number=123, name='Tom', skill='无极剑道'}

2、1 C语言代码实现

#include <stdio.h>
#include <stdlib.h>

// 结构 是自定义类型的一种
// typedef 类型定义,(类型重定义)  
typedef struct Node {
	int data;
	// next是指针,指向地址的类型是Node型
	struct Node* next;
}Node;

//初始化头结点函数
Node* initList() {
	//给指针变量分配一个Node型存储空间。
	Node* list = (Node*)malloc(sizeof(Node));
	list->data = 0;
	list->next = NULL;
	return list; 
}

//头插法
void headInset(Node* list, int data) {
	//给指针变量分配一个Node型存储空间。
	Node* node = (Node*)malloc(sizeof(Node));
	node->data = data;
	node->next = list->next;
	// 理解插入节点变成头结点
	list->next = node;
	
}

//尾插法
void tailInsert(Node* list, int data) {
	Node* temp = list;
	Node* node = (Node*)malloc(sizeof(Node));
	node->data = data;
	node->next = NULL;
	//找到尾
	while (temp->next)
	{
		temp = temp->next;
	}
	temp->next = node;
}
// 删除操作
//默认数据无重复
void deleteNum(Node* list, int data) {
	Node* temp = list->next;
	Node* pre = list;
	//找到待删除节点
	while (temp) {
		if (temp->data ==  data)
		{
			//删除
			pre->next = temp->next;
			
			//释放内存
			free(temp);

			//如果有重复数据,不要break

			break;
		}
		//往后移动一个节点
		pre = temp;
		temp = temp->next;
	}
	
}

// 打印
void printList(Node* list) {
	Node* temp = list->next;
	while (temp)
	{
		printf("%d", temp->data);
		temp = temp->next;
	}
	printf("\n");
}



int main() {
	Node* list = initList();
	printf("头插结果:");
	headInset(list, 1);
	headInset(list, 2);
	headInset(list, 3);
	headInset(list, 4);
	printList(list);
	printf("尾插56插结果:");
	tailInsert(list, 5);
	tailInsert(list, 6);
	printList(list);
	
	printf("删除3 后结果:");
	deleteNum(list, 3);
	
	printList(list);

	return 0;
}

2.2 运行结果:

在这里插入图片描述


持续学习更新,学成挣大钱。太忙,可能会迟到,但不会缺席!

欢迎每个小伙伴关注收藏,会全部回关,永远不会取消!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1558794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

03-MySQl数据库的-用户管理

一、创建新用户 mysql> create user xjzw10.0.0.% identified by 1; Query OK, 0 rows affected (0.01 sec) 二、查看当前数据库正在登录的用户 mysql> select user(); ---------------- | user() | ---------------- | rootlocalhost | ---------------- 1 row …

Docker:使用MinIO搭建对象存储平台

请关注微信公众号&#xff1a;拾荒的小海螺 1、简述 MinIO是一个基于对象存储技术的开源项目&#xff0c;它可以帮助用户快速搭建起私有的、高性能的对象存储平台。MinIO兼容Amazon S3 API&#xff0c;使得用户可以使用标准的S3工具和SDK来访问和管理MinIO存储的数据。此外&a…

查找--二分查找(Binary Search)

二分查找属于静态查找表&#xff0c;当以有序表表示静态查找表时&#xff0c;查找函数可用折半查找来实现。 查找过程&#xff1a;先确定待查记录所在的范围&#xff08;区间&#xff09;&#xff0c;然后逐步缩小范围直到找到或找不到该记录为止。 以处于区间中间位置记录的…

B样条曲线(记录)

B样条曲线的生成靠的两点&#xff1a; 1、控制点 2、基函数 B样条曲线的基函数是一个De Boor的递归表达式[1]&#xff1a; (1) (2) 其中是第个阶基函数。 而B样条曲线可以表示为[2]&#xff1a; (3) 如何理解上式&#xff1f;首先&#xff0c;我们知道&#xff0c;如果一个函数…

高端的电子画册,手机打开你见过吗?

手机阅读的高端电子画册&#xff0c;你见过吗&#xff1f;随着移动互联网的发展&#xff0c;越来越多的人选择在手机上阅读电子画册&#xff0c;而不是传统的纸质画册。这种趋势不仅节省了纸张资源&#xff0c;还提升了阅读体验。用户可以通过触摸屏幕、放大缩小、翻页等操作与…

【Blockchain】区块链浏览器 | 以太坊Etherscan比特币Blockchain门罗币Monero

区块链浏览器概述 区块链浏览器是一种软件,它使用API(应用程序编程接口)和区块链节点从区块链中提取各种数据&#xff0c;然后使用数据库来排列搜索到的数据&#xff0c;并以可搜索的格式将数据呈现给用户。 用户的输入是资源管理器上的可搜索项&#xff0c;然后通过数据库上…

empdll文件安装在哪里,详细的修复教程分享

在我们运行《荒野大镖客2》游戏的时候&#xff0c;有些玩家在游玩过程中可能会遇到emp.dll文件丢失的问题。此文件作为游戏运行过程中不可或缺的动态链接库&#xff08;DLL&#xff09;组件之一&#xff0c;丢失会导致游戏无法正常运行。小编将介绍5种解决emp.dll文件丢失的方法…

linux安装Zookeeper的详细步骤

1.Java环境确认 确保已经安装了Java环境&#xff0c;没有的自行安装 2.官网下载包 Apache ZooKeeper 3.安装 3.1上传到linux&#xff0c;解压 我的目录为/root/apache-zookeeper-3.8.4-bin 进入到/root/apache-zookeeper-3.8.4-bin/conf目录下&#xff0c;执行命令复制zoo…

C++2D原创我的世界1.00.3版本上市!!!

我很郁闷&#xff0c;为什么就是整不了昼夜交替啊喂&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 虽然这看上去很简单&#xff0c;但做起来要我命&#xff01;&#xff01;&#xff01; 优化过后总共1312行&#xff0c…

微信公众号迁移公证书在哪?

公众号迁移有什么作用&#xff1f;只能变更主体吗&#xff1f;很多小伙伴想做公众号迁移&#xff0c;但是不知道公众号迁移有什么作用&#xff0c;今天跟大家具体讲解一下。首先公众号迁移最主要的就是修改公众号的主体了&#xff0c;比如我们公众号原来是A公司的&#xff0c;现…

指针强化练习(详解)

更多学习内容 结构体内存对齐 和 位段-CSDN博客指针初级&#xff08;基础知识&#xff09;-CSDN博客指针进阶(深入理解)-CSDN博客 目录 1.sizeof与strlen的区别 2.一维数组 3.字符指针 4.二维数组 5.指针运算(笔试题) 6.函数指针 1.sizeof与strlen的区别 请思考以下运行结…

第1章.提示词:开启AI智慧之门的钥匙

什么是提示词&#xff1f; 提示词&#xff0c;是引导语言模型的指令&#xff0c;让用户能够驾驭模型的输出&#xff0c;确保生成的文本符合需求。 ChatGPT&#xff0c;这位文字界的艺术大师&#xff0c;以transformer架构为基石&#xff0c;能轻松驾驭海量数据&#xff0c;编织…

Chrome浏览器隐藏的截图功能配置及使用

来自实用又方便&#xff0c;轻松打开Chrome浏览器隐藏的截图功能&#xff01;​​​​​​​ 一、通过谷歌Chrome浏览器 现在直接通过谷歌Chrome浏览器内置功能&#xff0c;免安装扩充插件也可以实现Chrome的截图和长截图功能了&#xff01; 也不需要额外安装任何截图工具 &a…

【C++航海王:追寻罗杰的编程之路】priority_queue(优先队列) | 容器适配器你知道哪些?

目录 1 -> priority_queue的介绍和使用 1.1 -> priority_queue的介绍 1.2 -> priority_queue的使用 1.3 -> priority_queue的模拟实现 2 -> 容器适配器 2.1 -> 什么是适配器 2.2 -> STL标准库中stack和queue的底层结构 2.3 -> deque的介绍 2.…

吐丝的蜘蛛-第15届蓝桥第5次STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第176讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

MySQL面试必备一之索引

本文首发于公众号&#xff1a;Hunter后端 原文链接&#xff1a;MySQL面试必备一之索引 在面试过程中&#xff0c;会有一些关于 MySQL 索引相关的问题&#xff0c;以下总结了一些&#xff1a; MySQL 的数据存储使用的是什么索引结构B 树的结构是什么样子什么是复合索引、聚簇索…

嵌入式第一部分-第一集:ARM那些你得知道的事

ARM&#xff1a;Advanced RISC Machine&#xff0c;先进精简指令集机器 ARM公司只做设计&#xff0c;不生产。 国内IC生产厂商&#xff1a;华为海思、全志、瑞芯微、MTK&#xff08;联发科&#xff09; 扩展&#xff1a;ARM的商业模式了解。 使用三星S5PV210开发板进行视频的讲…

红黑树介绍及插入操作的实现

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

CubeIDE 下如何将版本号和日期关联。

1. 使用__DATE__ 和__TIME__获取编译日期和时间。 2. 将__DATE__ 和__TIME__转换成UINT 3. 将转换后的数赋值给版本号。 4. 设置工程保证每次都会重新编译对应文件。 对应函数如下&#xff1a; uint8_t VER_MAIN; uint8_t VER_SUB; uint8_t VER_MIN; #include <stdlib.…

原子类 AtomicReference 详解

通过对 AtomicInteger、AtomicBoolean 和 AtomicLong 分析我们发现&#xff0c;这三个原子类只能对单个变量进行原子操作&#xff0c;那么我们如果要对多个变量进行原子操作&#xff0c;这三个类就无法实现了。那如果要进行多个变量进行原子操作呢&#xff1f;操作方式就是&…