2、java数据结构和算法:单链表: 反转,逆序打印, 合并二个有序链表,获取倒数第n个节点, 链表的有序插入
什么也不说, 直接上代码:
功能点有:
1, 获取尾结点
2, 添加(添加节点到链表的最后面)
3, 添加(根据节点的no(排名)的大小, 有序添加)
4, 单向链表的 遍历
5, 链表的长度
6, 删除某一个节点
7, 更换指定位置的节点
8, 查询第n个节点
9, 查询倒数第n个节点
10, 链表反转, 使用递归实现
11, 逆序打印
12, 合并二个有序链表, 且结果仍然是有序的
//英雄节点
class HeroNodeLv{
public int no;//英雄排名
public String name;//名字
public String nickName;//花名
public HeroNodeLv next;//指向下一节点
public HeroNodeLv(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNodeLv{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
//链表对象
class SingleLinkListLvcai {
//单链表是由节点组成, 节点由 数据+ next(指向下一节点)组成
// 定义一个头结点,为空
public HeroNodeLv head = new HeroNodeLv(0,"","");
public void setHead(HeroNodeLv head) {
this.head = head;
}
// 获取头结点
public HeroNodeLv getHeadNode(){return head;}
//1, 获取尾结点
public HeroNodeLv getLastNode(){
//head头结点不能动, 定义第三方对象来遍历
HeroNodeLv temp = head;
while(true){
if(temp.next == null){
//说明是尾结点
return temp;
}
temp = temp.next;
}
}
//2, 添加(添加节点到链表的最后面)
public void add(HeroNodeLv node){
//head头结点不能动, 定义第三方对象来遍历
HeroNodeLv temp = head;
while(true){
if(temp.next == null){
//说明是尾结点
break;
}
temp = temp.next;
}
//遍历完后,此时temp就是尾结点
temp.next = node;
}
//3, 添加(根据节点的no(排名)的大小, 有序添加)
public void addByHeroNo(HeroNodeLv node){
HeroNodeLv temp = head;
boolean flag = false; //该节点是否已存在标识, 默认false,不存在
while(true){
if (temp.next == null) {
//说明到尾节点
break;
}
if(temp.next.no > node.no){
//说明 node 是需要放在 temp的下一个节点
break;
}else if(temp.next.no == node.no){
flag = true;//该节点已存在
break;
}
temp = temp.next;
}
if(false){
System.out.println("该节点已存在");
}else{
//插在temp的后面, 这里先将node的next指定好,之后,再指定插入, 这二行代码顺序不能变,否则会出现死循环
node.next = temp.next;
temp.next = node;
}
}
//4, 单向链表的 遍历
public void show(){
if(head.next== null){
//空链表
System.out.println("空链表");
return;
}
HeroNodeLv temp = head;
while(true){
if(temp.next == null){
break;
}
System.out.println(temp);
temp = temp.next;
}
System.out.println(temp);
}
//5, 链表的长度
public int length(){
if(head.next == null){
return 0;//这里头节点 不计入长度
}
HeroNodeLv temp = head.next;//这里头节点 不计入长度
int count = 0;
while(temp!= null){
count++;
temp = temp.next;
}
return count;
}
//6, 删除某一个节点
public void delNode(int no){
HeroNodeLv temp = head;
boolean flag = false;//该链表是否存在这个节点,默认为false, 不存在
while(true){
if(temp.next == null){
break;//链表尾部
}
if(temp.next.no == no){
flag = true;
break;//删除此时的这个节点的下一节点
}
temp = temp.next;
}
//循环完后,,此时temp的 next就是要删除的节点
if(flag){
temp.next = temp.next.next;
}else {
System.out.println("链表中不存在这个节点");
}
}
//7, 更换指定位置的节点
public void updateNode(int no,HeroNodeLv node){
HeroNodeLv temp = head;
boolean flag = false;//该链表是否存在这个节点, 默认为false 不存在
while (true) {
if (temp.next == null) {
break;//链表尾部
}
if (temp.next.no == no) {
flag = true; //temp的next就是要替换的节点
break;
}
temp = temp.next;
}
if (flag) {
//更换
temp.next = node;//更换next.
node.next = temp.next.next;//指定node的next
}else{
System.out.println("不存在这个节点");
}
}
//8, 查询第n个节点
public HeroNodeLv getByNo(int no){
//获取链表长度
if(no == 0){
return getHeadNode();//头结点
}
if(no >length()){
System.out.println("超出链表的长度:"+length());
return null;
}
HeroNodeLv temp = head.next;
int count = 0;
while(temp != null){
count++;
if(count == no){
//这就是要找的节点
break;
}
temp = temp.next;
}
return temp;
}
//9, 查询倒数第n个节点
public HeroNodeLv getByBackwordNum(int no){
//思路: 查询倒数第n个节点, 就是查询正数第 length-n+1 个节点
//如果为0 或者超出链表长度, 返回null
if(no == 0 || no > length()){
System.out.println("不能为0,或者,超出链表长度:链表长度为"+length());
return null;
}
return getByNo(length() - no +1);
}
}
//10, 链表反转, 使用递归实现
public static void reverseList(HeroNodeLv node){
//思路: 遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表reverseHead 的最前端
if(node.next == null || node.next.next == null){
return ;//空链表,只有一个节点的链表
}
HeroNodeLv cur = node.next;//定义指针变量,便于遍历原来的链表
HeroNodeLv next = null;//next 指的是当前节点(cur)的下一个节点
HeroNodeLv reverseHead = new HeroNodeLv(0,"","");
while(cur!= null){
next = cur.next;//先保存当前节点的写一个节点
cur.next = reverseHead.next;//将cur的下一个节点 指向新链表的最前端
reverseHead.next = cur;//将cur连接到新的链表上
cur = next;//后移
}
//循环完之后,newNode就是一个反转的链表了,,此时将newNode链表的头节点 , 变为原来链表的头节点
node.next = reverseHead.next;
}
//11, 逆序打印
public static void reversePrint(HeroNodeLv node){
//思路: 将单链表遍历,一个个取出,放到栈中,然后栈遍历, 利用栈的特点:先进后出
if(node.next == null){
return;
}
HeroNodeLv cur = node.next;
Stack<HeroNodeLv> stack = new Stack<HeroNodeLv>();
while(cur != null){
stack.push(cur);
cur = cur.next;
}
//遍历stack
while(stack.size() > 0){
System.out.println(stack.pop());
}
}
//12, 合并二个有序链表, 且结果仍然是有序的, 此方法的入参节点,从第一个节点开始, 不带头节点
public static HeroNodeLv mergeLinkList(HeroNodeLv node1 ,HeroNodeLv node2){
if(node1 == null && node2 == null){
return null;
}
if(node1 == null){
return node2;
}
if (node2 == null) {
return node1;
}
HeroNodeLv head = null ;
if(node1.no > node2.no){
head = node2;
head.next = mergeLinkList(node1,node2.next);
}else if(node1.no < node2.no){
head = node1;
head.next = mergeLinkList(node1.next,node2);
}else{
//相等的情况
head = node1;
head.next = mergeLinkList(node1.next,node2.next);
}
return head;
}
测试结果:
合并链表:
public static void main(String[] args) {
HeroNodeLv node1 = new HeroNodeLv(1, "宋江", "及时雨");
HeroNodeLv node2 = new HeroNodeLv(2, "吴用", "神算子");
HeroNodeLv node3 = new HeroNodeLv(3, "卢俊义", "玉麒麟");
HeroNodeLv node4 = new HeroNodeLv(4, "武松", "打老虎");
HeroNodeLv node5 = new HeroNodeLv(5, "吕财", "打老虎");
HeroNodeLv node6 = new HeroNodeLv(6, "吴二娘", "打老虎");
HeroNodeLv node7 = new HeroNodeLv(7, "吴二娘", "打老虎");
HeroNodeLv node8 = new HeroNodeLv(8, "吴二娘", "打老虎");
HeroNodeLv node9 = new HeroNodeLv(9, "吴二娘", "打老虎");
HeroNodeLv node10 = new HeroNodeLv(10, "吴二娘", "打老虎");
SingleLinkListLvcai linkListLv = new SingleLinkListLvcai();
linkListLv.add(node1);
linkListLv.add(node7);
linkListLv.add(node8);
linkListLv.addByHeroNo(node3);//这里的添加,是有序添加
linkListLv.addByHeroNo(node9);
System.out.println("链表linkListLv:");
linkListLv.show();// 1-3-7-8-9
System.out.println("==============================================");
SingleLinkListLvcai linkListLv2 = new SingleLinkListLvcai();
linkListLv2.addByHeroNo(node7);
linkListLv2.addByHeroNo(node4);
linkListLv2.addByHeroNo(node2);
linkListLv2.addByHeroNo(node8);
linkListLv2.addByHeroNo(node6);
linkListLv2.addByHeroNo(node5);
System.out.println("链表linkListLv2:");
linkListLv2.show();//2-4-5-6-7-8
System.out.println("==============================================");
HeroNodeLv heroNodeLv = mergeLinkList(linkListLv.getHeadNode().next, linkListLv2.getHeadNode().next);
//合并后的链表没有头结点,所以需要加上头结点
HeroNodeLv newLinkList = new HeroNodeLv(0, "", "");
newLinkList.next= heroNodeLv;
linkListLv.setHead(newLinkList);
System.out.println("合并后的新链表为:newLinkList");
linkListLv.show();//1-2-3-4-5-6-7-8
}
合并二个有序链表结果:


链表反转结果:


链表反转打印的结果,不破坏原有链表结构:


获取链表倒数第n个节点:


其余的几个功能点可以自己测试......
2、java数据结构和算法:单链表: 反转,逆序打印, 合并二个有序链表,获取倒数第n个节点, 链表的有序插入的更多相关文章
- C++面试常见问题——04链表的逆序与合并
链表的逆序与合并 链表的逆序 已知一个链表的头指针为head,将该链表逆序. #include<iostream> using namespace std; struct Node{ in ...
- [剑指offer] 14. 链表中倒数第K个节点+翻转+逆序打印+合并两个排序链表 + 链表相交(第一个公共节点) (链表)
题目描述 输入一个链表,输出该链表中倒数第k个结点. 思路: 两个指针,起始位置都是从链表头开始,第一个比第二个先走K个节点,当第一个走到链表尾时,第二个指针的位置就是倒数第k个节点.(两指针始终相 ...
- Java实现单链表的逆序打印
思路1:可以将链表进行反转,然后进行数据的输出即可,单链表反转地址如下https://blog.csdn.net/Kevinnsm/article/details/113763272 这个思路1肯定有 ...
- 6, java数据结构和算法: 栈的应用, 逆波兰计算器, 中缀表达式--> 后缀表达式
直接上代码: public class PolandCalculator { //栈的应用:波兰计算器: 即: 输入一个字符串,来计算结果, 比如 1+((2+3)×4)-5 结果为16 public ...
- Java数据结构和算法(一)线性结构之单链表
Java数据结构和算法(一)线性结构之单链表 prev current next -------------- -------------- -------------- | value | next ...
- Java数据结构和算法(四)--链表
日常开发中,数组和集合使用的很多,而数组的无序插入和删除效率都是偏低的,这点在学习ArrayList源码的时候就知道了,因为需要把要 插入索引后面的所以元素全部后移一位. 而本文会详细讲解链表,可以解 ...
- Java数据结构和算法(一)线性结构
Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
- java数据结构与算法之栈(Stack)设计与实现
本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...
随机推荐
- Windows域的管理
目录 域的管理 默认容器 组织单位的管理 添加额外域控制器 卸载域控服务器 组策略应用 域的管理 域用户账户的管理 创建域用户账户 配置域用户账户属性 验证用户的身份 授权或拒绝对域资源的访问 组的管 ...
- 解决Metasploit中shell乱码的问题
我们在kali中用 Metasploit 获取到windows主机的shell后,会出现乱码问题,归根到底,就是windows和linux系统的中文编码不同,所以导致windows系统上的中文在lin ...
- Windows 2003 Server远程代码执行漏洞集合
目录 MS08-067 CVE-2017-7269 MS08-067 发布日期:2008/10/22 针对端口:139.445 漏洞等级:高危 漏洞影响:服务器服务中的漏洞可能允许远程执行代码 受影响 ...
- 初探SQL注入需要知道的5个问题
SQL注入产生原理 可控变量(注入点,就是传参) 带入数据库查询 变量未存在过滤或过滤不严谨 例子: 获取admin表的pass里面的数据 select * from users where id=1 ...
- Github镜像网站
https://hub.fastgit.org
- python爬虫——《瓜子网》的广州二手车市场信息
由于多线程爬取数据比单线程的效率要高,尤其对于爬取数据量大的情况,效果更好,所以这次采用多线程进行爬取.具体代码和流程如下: import math import re from concurrent ...
- mysql 连表不要用varchar和int这两种不相同的类型做比较
他会默认你123abc等于123 说多了都是泪啊
- [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]
[并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...
- SDK安全测试
设备调试 strace MI 5X 链接:https://pan.baidu.com/s/1KfsfEgjniozXGUD_69m0SQ 提取码:mulo 推strace到手机中 adb push s ...
- 神奇的不可见空格<200b>导致代码异常
故事是这样发生的,在做一个JSON对象转化的时候,出现了转化异常:刚开始还是以为是格式错误,后来一步步排除,才发现是不可见空格<200b>导致的解析异常 出现 使用Typora编写文字时, ...