为得一份满意的offer,今天开始联系常用的数据结构,今日份——单链表
首先将一下单链表的基本内容吧
单链表作为我们平时最常见的数据结构之一,本身的结构并不是很复杂,用常语说就是一根用钩子钩起来的一条线,因此我们在编写链表的节点类时我们需要钩子属性,就是除了节点常用属性之外一个不参与节点信息存储的属性,创建并不复杂,就是节点类在属性名,实例:
public HodeNode next;
为什么该属性是public而不是private,因为作为钩子属性,是需要可以被从外界拿到的属性,这让才能节点之间一个一个连接起来,节点的代码样例如下:
class HodeNode{
private int id;
private String name;
//下一个节点指针
public HodeNode next;
public HodeNode(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "HodeNode{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
在我们创建好链表所需要的节点之后,我们就要开始编写链表的常用方法了,比如增加节点,删除节点,遍历等等方法。
在编写常用方法之前,我们需要创建一个头节点,该节点的作用就是为了链表遍历的时候使用,创建样例如下:
private HodeNode head = new HodeNode(0,"");
先讲讲增加节点吧。增加节点我们采用最平常的直接在后面追加的方式,跟StringBuffer或StringBuilder的append()方法一样,直接追加在链表最后面,实现原理我们一步一步来。
- 创建一个临时节点用来替代头节点,用此临时节点来进行遍历链表
- 使用while()循环进行链表遍历
- 进行循环便要考虑循环终止的条件,那就是循环到最后一个节点时结束循环
- 在这里我们可以做一个去重处理,也可以不做,看个人需求。去重操作实现也很简单,创建一个标识属性,比如boolean flag;通过该属性去判断链表中是否有无重复的节点。
- 遍历的时候需要将节点后移,起到遍历的效果
- 遍历完之后将节点使用钩子属性连接上
public void add(HodeNode hodeNode){
HodeNode temp = head;
boolean flag = false;
while (true){
if (temp.next == null){
break;
}
if (temp.next.getId() == hodeNode.getId()){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
System.out.println("该编号"+hodeNode.getId()+"已经存在");
}else {
temp.next = hodeNode;
}
}
好了,增加的方法讲完了,接下来是遍历的方法了,就不想前面那么赘叙了,简单的讲一下,因为遍历的实现非常的简单,遍历的效果就是将链表的各个节点遍历出来,前面增加方法的代码里面就有体现,代码如下:
public void list(){
if (head.next == null){
return;
}
HodeNode temp = head;
System.out.println("单链表的数据为:");
while (true){
if (temp.next == null){
break;
}
System.out.println(temp.next);
temp = temp.next;
}
}
好了,遍历和增加都有了,依据我们CRUD的习惯,删除那是必不可少啦,删除的代码逻辑非常的简单。根据传入的节点HodeNode找到链表中对应的节点,将找到的节点的钩子函数释放掉就实现了删除操作,代码如下:
public void pop(HodeNode hodeNode){
if (head.next == null){
return;
}
HodeNode temp = head;
while (true){
if (temp.next == null){
break;
}
if (temp.next.getId() == hodeNode.getId()){
temp.next = temp.next.next;
}
temp = temp.next;
}
}
我们在编写接口的时候,需求一般都会有根据对应的id查找数据,我们的单链表也不例外,实现方法跟删除操作的逻辑相似。根据传入的id查找到节点中的唯一标识id就将该节点返回出来,代码如下:
public HodeNode get(int id){
if (head.next == null){
return null;
}
HodeNode temp = head;
while (true){
if (temp.next == null){
return null;
}
if (temp.getId() == id){
return temp;
}
temp = temp.next;
}
}
在这里我没有编写修改的方法,修改方法和删除和查找的方法一样,通过传入的id去查找链表中存放的位置,然后将找到的节点信息修改成需要修改的信息即可,代码有兴趣的朋友可以自己实现一下。
我根据自己的想法增加了一个按id序列的顺序编写了一个插入的方法,方法实现很简单,通过id的比较,找到对应的位置,将节点插入进去。代码如下:
public void insertNode(HodeNode hodeNode){
//检查链表是否为空
if (head.next == null) {
head.next = hodeNode;
return;
}
HodeNode temp = head;
boolean flag = false;
while (true){
//检查下一个节点是否为空,以此判断是否到达链表末尾
if (temp.next == null){
break;
}
if (temp.next.getId() > hodeNode.getId()){
break;
}
if (temp.next.getId() == hodeNode.getId()){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
System.out.println("该编号"+hodeNode.getId()+"已经存在");
}else {
hodeNode.next = temp.next;
temp.next = hodeNode;
}
}
根据上面所阐述的信息,我将单链表的实现都简单的说明了一下,下面的代码是包含节点、链表和测试的代码,有需要的朋友可以看看。
/**
* 单链表
*/
public class SingletonLinkedListDemo {
public static void main(String[] args) {
SingletonLinkedList singletonLinkedList = new SingletonLinkedList();
HodeNode hodeNode1 = new HodeNode(1,"qqq");
HodeNode hodeNode2 = new HodeNode(2,"www");
HodeNode hodeNode3 = new HodeNode(3,"ttt");
HodeNode hodeNode4 = new HodeNode(4,"eee");
HodeNode hodeNode5 = new HodeNode(5,"rrr");
singletonLinkedList.add(hodeNode1);
singletonLinkedList.add(hodeNode2);
singletonLinkedList.add(hodeNode2);
singletonLinkedList.add(hodeNode4);
singletonLinkedList.add(hodeNode5);
singletonLinkedList.add(hodeNode5);
System.out.println("=========遍历============");
singletonLinkedList.list();
System.out.println("=========查询============");
System.out.println(singletonLinkedList.get(1));
System.out.println("=========删除============");
singletonLinkedList.pop(hodeNode2);
System.out.println("=========删除后的遍历============");
singletonLinkedList.list();
System.out.println("=========删除后的查询============");
System.out.println(singletonLinkedList.get(1));
System.out.println("=========按顺序插入之后遍历============");
singletonLinkedList.insertNode(hodeNode2);
singletonLinkedList.insertNode(hodeNode3);
singletonLinkedList.insertNode(hodeNode3);
singletonLinkedList.list();
}
}
class SingletonLinkedList{
//创建一个头节点,方便遍历
private HodeNode head = new HodeNode(0,"");
//添加单链表节点
public void add(HodeNode hodeNode){
HodeNode temp = head;
boolean flag = false;
while (true){
if (temp.next == null){
break;
}
if (temp.next.getId() == hodeNode.getId()){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
System.out.println("该编号"+hodeNode.getId()+"已经存在");
}else {
temp.next = hodeNode;
}
}
//获取单链表节点
public HodeNode get(int id){
if (head.next == null){
return null;
}
HodeNode temp = head;
while (true){
if (temp.next == null){
return null;
}
if (temp.getId() == id){
return temp;
}
temp = temp.next;
}
}
//删除单链表节点
public void pop(HodeNode hodeNode){
if (head.next == null){
return;
}
HodeNode temp = head;
while (true){
if (temp.next == null){
break;
}
if (temp.next.getId() == hodeNode.getId()){
temp.next = temp.next.next;
}
temp = temp.next;
}
}
//遍历单链表
public void list(){
if (head.next == null){
return;
}
HodeNode temp = head;
System.out.println("单链表的数据为:");
while (true){
if (temp.next == null){
break;
}
System.out.println(temp.next);
temp = temp.next;
}
}
//按照大小序列插入节点
public void insertNode(HodeNode hodeNode){
//检查链表是否为空
if (head.next == null) {
head.next = hodeNode;
return;
}
HodeNode temp = head;
boolean flag = false;
while (true){
//检查下一个节点是否为空,以此判断是否到达链表末尾
if (temp.next == null){
break;
}
if (temp.next.getId() > hodeNode.getId()){
break;
}
if (temp.next.getId() == hodeNode.getId()){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
System.out.println("该编号"+hodeNode.getId()+"已经存在");
}else {
hodeNode.next = temp.next;
temp.next = hodeNode;
}
}
}
//创建节点类
class HodeNode{
private int id;
private String name;
//下一个节点指针
public HodeNode next;
public HodeNode(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "HodeNode{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
到此,我个人的单链表阐述到此结束,如有不对的地方麻烦各位大佬指出。