链表
单链表
Linked List链表 是一种有序的列表:
- 链表是 以结点的方式来存储,为链式存储
- 每个结点 包含data域,next域(指向下一结点)
- 链表的 各个结点不一定是连续存储
- 链表分为 带头节点 和 无头节点 的链表
- 添加节点: 头插法 与 尾插法
创建节点
- 使用一个 Node对象来代表结点,node中包含 data 和 next data;
- 定义一个 SingleLinkedList类 来管理链表
结点对象
//每一个对象 代表一个 节点
class HeroNode{
public int no;
public String name;
public String nickname;
public HeroNode next; //指向下一个节点(对象表示节点)
public HeroNode(int no,String name,String nickname){
this.no = no;
this.name = name;
this.nickname = nickname;
}
}
初始化链表
class SingleLinkedList{
//初始化头节点
private HeroNode head = new HeroNode(0,null,null);
public HeroNode getHead(){
return head;
}
//添加节点方法
public void add(HeroNode node){
//先找到头节点 并赋值给 temp临时变量
HeroNode temp = head;
//1.遍历链表,找到最后
while (true){
if (temp.next==null)
break;
temp = temp.next;
}
//2.给最后的next赋值
temp.next = node;
}
}
增删改操作
找到待操作结点的前一个结点,然后进行 操作
删除,修改节点
public void delete(int no){
Node temp = head;
while (temp.next!=null){
if (temp.next.no == no){
temp.next = temp.next.next;
return;
}
temp = temp.next;
}
System.out.println("未找到该编号结点");
}
public void update(Node newNode){
Node temp = head;
while (temp.next!=null){
if(temp.next.no == newNode.no){
temp.next.name = newNode.name;
return;
}
temp = temp.next;
}
System.out.println("未找到该编号结点");
}
按编号顺序插入节点
public void addByOrder(Node node){
Node temp = head;
while (temp.next!=null){
//按编号从小到大放入结点 1,2,4 -- 3
if (temp.next.no > node.no){
break;
}
if (temp.next.no==node.no){ //相同编号--更新
node.next = temp.next.next;
temp.next = node;
return;
}
temp = temp.next;
}
//插入该节点
node.next = temp.next;
temp.next = node;
}
//打印链表
public void show(){
if (head.next==null){
System.out.println("空链表~");
return;
}
Node temp = head.next;
while (temp!=null){
System.out.println(temp);
temp=temp.next;
}
}
单链表面试题
1. 求链表中节点的个数
public static int getLength(HeroNode head){
if (head.next == null){
System.out.println("空链表~");
return 0;
}
int length=0;
HeroNode temp = head;
while (temp.next!=null){
length++;
temp=temp.next;
}
return length;
}
2. 查找链表中倒数第k个结点
public Node findLastNode(Node head,int index){
//1.获取链表长度
int length = getLength(head);
if (index<=0 || index>length){
System.out.println("该节点不存在");
return null;
}
Node temp = head.next;
//2. length-index = 结点位置 倒数第二个3-2=1
for (int i = 0; i < length-index; i++) {
temp = temp.next;
}
return temp;
}
3. 单链表反转
/*遍历原链表,头插法创建新链表*/
public void reverse(Node head){
//1.链表只有一个结点或为空
if (head.next==null || head.next.next==null){
return ;
}
//2.创建反转链表
//a.遍历原链表
Node temp = head.next; //存放遍历的结点
Node temp2 = temp.next; //记录遍历的下一个结点
Node tempHead = new Node(0,null);//新链表的头结点
while (temp!=null){
temp2 = temp.next; //记录下一个要遍历的结点
//b.头插法 插入结点
temp.next = tempHead.next;
tempHead.next = temp;
temp = temp2;
}
head.next = tempHead.next;
}
4. 单链表逆序打印
/*使用栈,在不破坏原有结构的情况下逆序输出链表*/
public void reversePrint(Node head){
if (head.next==null){
System.out.println("空链表");
return;
}
//1.将结点全部压入链表
Stack<Node> stack = new Stack();
Node temp = head.next;
while (temp!=null){
stack.push(temp);
temp = temp.next;
}
//2.弹出结点 并打印
while (!stack.isEmpty()){
System.out.println(stack.pop());
}
}
双向链表
对比:
- 单链表查找方向只能是一个,双向链表可以前后查找
- 单链表不能 自我删除,需要靠temp前置结点。

双向链表代码
class DoubleLinkedList{
private Node2 head;
public DoubleLinkedList(){
this.head = new Node2(0,null);
}
/*增删改*/
public void add(Node2 node){
Node2 temp = head;
//1.遍历到最后一个链表
while (temp.next!=null){
temp = temp.next;
}
temp.next = node;
node.pre=temp;
}
public void addByOrder(Node2 node){
Node2 temp = head;
while (temp!=null){
if (temp.no > node.no){ //a.小于当前结点,往前插入 1,2,4--3
node.next = temp;
node.pre = temp.pre;
temp.pre.next = node;
temp.pre = node;
return;
}
if (temp.no == node.no){ //c.编号一致 更新改结点
temp.name = node.name;
return;
}
if (temp.next == null){ //b.插入到最后的情况
temp.next = node;
node.pre = temp;
return;
}
temp = temp.next;
}
}
//找到要修改的结点:进行更新/删除操作
public void update(Node2 node){
Node2 temp = head.next;
while (temp!=null){
if (temp.no == node.no){
temp.name = node.name;
System.out.println("更新完成");
return;
}
temp = temp.next;
}
System.out.println("未找到该编号结点");
}
public void delete(int no){
Node2 temp = head.next;
while (temp!=null){
if (temp.no == no){
temp.pre.next = temp.next;//自我删除
if (temp.next!=null) { //若要删除的节点为最后一个节点 它没有后置节点
temp.next.pre = temp.pre;
}
System.out.println("删除完成");
return;
}
temp = temp.next;
}
System.out.println("未找到该编号结点");
}
public void show(){
if (head.next==null){
System.out.println("空链表~");
return;
}
Node2 temp = head.next;
while (temp!=null){
System.out.println(temp);
temp = temp.next;
}
}
}
环形链表
单向环形链表

创建与遍历环形链表
//单向环形链表
class CircularLinkedList{
public Node head;
public CircularLinkedList(){
head = new Node(0,null);
}
/*创建环形链表: temp一直指向最后一个结点*/
public void add(int num){
if (num<1){
System.out.println("请输入正确num值");
return;
}
Node temp = null; //记录最后一个结点位置
for (int i = 1; i <= num; i++) {
Node node = new Node(i,"环形链表");
if (i==1){ //添加第一个结点的情况
head = node;
head.next = node; //指向自己构成环
temp = head;
}else { //加入结点
node.next = temp.next; //新插入的节点继承环
temp.next = node;
temp = node;
}
}
}
public void list(){
if (head==null){
System.out.println("空链表~");
return;
}
Node temp = head;
while (true){
System.out.println(temp);
temp = temp.next;
if (temp==head){
break;
}
}
}
}
约瑟夫Josehu 问题:
有 n 个小孩做一圈,从第k个人开始报数,每次数m下, 看最后留下的是谁
【5个小孩,从第一个开始,每轮数2下; 1,2-->第二个小孩出去 第三个小孩重复上述】
- 创建temp节点,指向first的前一个(用于删除节点)
- first与temp 后移 k-1 次,准备报数
- while循环开始 出圈:
- 每次 报数,first与temp 后移m-1 次
- 弹出 first所指节点,first指向下一个(first=first.next; temp.next=first)
- temp=first 只剩一个节点,出圈完毕。

代码实现
/**
* 约瑟夫环问题
* @param start 开始位置
* @param no 每轮报几个数
* @param num 总人数(环大小)
*/
public void Josehu(int start,int no,int num){
if (start>num || no>num ||start<1 ||no<1){
System.out.println("参数有误");
return;
}
//1.初始化
//a.创建环
add(num);
//b.移动到start开始位置 ,并创建temp指向开始位置的前一个
Node temp = head;
for (int i = 1; i < start; i++) { //从1开始
head = head.next;
}
while (temp.next!=head){
temp = temp.next;
}
System.out.println("移动后:"+"temp:"+temp+"\nhead:"+head);
//2.遍历环,报数 出圈
while (true){
//a.报数 移动 k-1次
for (int i = 0; i < no-1; i++) {
head = head.next;
temp = temp.next;
}
//b.出圈
System.out.printf("编号为%d的小孩出圈\n",head.no);
head = head.next;
temp.next = head;
//c.只剩最后一个结点
if (temp==head){
System.out.println("最后一个编号为%d的小孩出圈"+head.no);
break;
}
}
}
我是菜鸡啊

浙公网安备 33010602011771号