2020-05-29数据结构与算法-链表
1、链表:非连续和非顺序
解决的问题:增删慢的问题
2、构建链表
public class Node<T> {
//存储元素
public T item;
//下一个结点
public Node next;
public Node( T item,Node next) {
this.item=item;
this.next=next;
}
public void main(String[] args) {
//构建结点 ,此时没有指向,只有值
Node<Integer> first=new Node<Integer>(11,null);
Node<Integer> second=new Node<Integer>(13,null);
Node<Integer> third=new Node<Integer>(12,null);
Node<Integer> four=new Node<Integer>(15,null);
Node<Integer> five=new Node<Integer>(17,null);
//生成链表,给定指向
first.next=second;
second.next=third;
third.next=four;
four.next=five;
}
}
3、单向链表:(一个数据+一个指针)
头结点:无值,有指向,找到链表的入口。
练习题一、
注意:堆是先进先出,栈是先进后出
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
import java.util.*;
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
//定义一个栈
Stack<Integer> st=new Stack<Integer>(); //定义一个栈
//定义一个动态数组
ArrayList<Integer> array=new ArrayList<Integer>();
//定义一个泛型数据
if(listNode==null){
return array;
}
//Integer temp;
// ListNode pre=listNode; //头结点
ListNode cur=listNode; //第一个结点
// for (int i=0;cur.next!=null;i++){
while(cur!=null){
st.push(cur.val);
cur=cur.next;//指向下一个结点
}
while(!st.empty()){
//temp=stack.pop();
array.add(st.pop());
}
return array;
}
}
扩展知识:队列
offer()方法往队列添加元素如果队列已满直接返回false,队列未满则直接插入并返回true;
add()方法是对offer()方法的简单封装.如果队列已满,抛出异常new IllegalStateException("Queue full");
put()方法往队列里插入元素,如果队列已经满,则会一直等待直到队列为空插入新元素,或者线程被中断抛出异常.
remove()方法直接删除队头的元素:
peek()方法直接取出队头的元素,并不删除.
element()方法对peek方法进行简单封装,如果队头元素存在则取出并不删除,如果不存在抛出异常NoSuchElementException()
poll()方法取出并删除队头的元素,当队列为空,返回null;
take()方法取出并删除队头的元素,当队列为空,则会一直等待直到队列有新元素可以取出,或者线程被中断抛出异常
练习题一、在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode deleteDuplication(ListNode pHead)
{
//安全性校验
if(pHead==null || pHead.next==null){
return pHead;
}//判断链表是否为空,是就输出原链表头结点
//定义一个辅助头结点head
ListNode head=new ListNode (Integer.MIN_VALUE);
head.next=pHead; //新头结点指向旧头结点
ListNode pre=head; //保存新头结点的值
ListNode cur=head.next; //保存旧结点的值
//判断当前结点是否与下一个结点相同,相同,则执行循环
while(cur!=null){
if(cur.next!=null && cur.next.val==cur.val){
while(cur.next!=null && cur.next.val==cur.val){
//相同,当前结点指向下一个结点
cur=cur.next;
}//找出重复的结点,当前结点的位置是最后一个重复结点的位置
//转向下一个结点
cur=cur.next;//转向重复结点的下一个位置
pre.next=cur;//把头结点指向当前结点
}else{
//不相同时就执行下一个操作,一直向下一位置运动
pre=cur;
cur=cur.next;
}
}
return head.next;
}
}