链表(Linked List)
一、概述
链表是有序的列表,他在内存中的存储如下:
- 链表以节点的方式存储,是链式存储结构
- 每个节点包含data域,next域:指向下一个节点
- 如图:链表的每个节点不一定是连续存储
- 链表分带头节点的链表和不带头节点的链表,根据实际需求来确定
二、单链表的创建与操作
2.1 添加
- 先创建一个head头节点,作用为表示单链表的头
- 每添加一个节点就直接加入到链表的最后
/**
* @author DELL
* @Date 2020/1/16 18:06
**/
public class SingleLinked {
public static void main(String[] args) {
MyLinked myLinked = new MyLinked();
myLinked.addVal(1);
myLinked.addVal(2);
myLinked.addVal(3);
myLinked.indexAdd(0,0);
myLinked.indexAdd(4,4);
myLinked.display();
}
}
class Node{
public int val;
public Node next;
public Node(int val){
this.val=val;
this.next=null;
}
}
class MyLinked{
Node head=null;
/**
* 尾插
* @param val
*/
public void addVal(int val){
Node node = new Node(val);
if(head==null){
head=node;
}else{
Node cur=head;
while(cur.next!=null){
cur=cur.next;
}
cur.next=node;
}
}
public void tailAdd(int val){
Node node = new Node(val);
Node cur=head;
if (head != null) {
node.next = cur;
}
head = node;
}
/**
* 遍历
*/
public void display(){
Node cur=head;
if(cur==null){
return;
}
while(cur!=null){
System.out.print(cur.val+" ");
cur=cur.next;
}
System.out.println();
}
/**
* 链表的长度
* @return
*/
public int length(){
Node cur=head;
int length=0;
while(cur!=null){
length++;
cur=cur.next;
}
return length;
}
private Node beforeNode(int index){
Node cur=head;
while(index-1>0){
cur=cur.next;
index--;
}
return cur;
}
/**
* 任意位置添加数据
* @param index
* @param val
*/
public void indexAdd(int index,int val){
Node node = new Node(val);
if(index==0){
tailAdd(val);
return;
}
Node node1 = beforeNode(index);
Node newNext=node1.next;
node1.next=node;
node.next=newNext;
}
}
2.2 删除
- 找到需要删除的这个节点的前一个节点cur
- cur.next=cur.next.next
- 被删除的节点将不会有其他引用指向,会被垃圾回收机制回收
/**
* 删除节点
* @param index
* @return
*/
public boolean deleteNode(int index){
Node cur = beforeNode(index);
if(cur==null){
System.out.println("没有此节点!");
return false;
}
if(index==0){
head=head.next;
return true;
}
cur.next=cur.next.next;
return true;
}
栈(Stack)
一、概述
- 栈是一个先入后出(FILO-First In Last Out)的有序列表
- 限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端为变化的一端,称为栈顶(Top),另一端称为栈底(Bottom)
- 最先放入栈中的元素在栈底,最后放入的元素在栈顶,而删除元素时最先放入的元素后删除,最后放入的元素先删除。
二、图解入栈和出栈
1. 入栈
2. 出栈
三、栈的应用场景
- 子程序调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,知道子程序执行完毕后再将地址取出,以回到原来的程序
- 递归调用:和子程序调用类似,只是除了存储下一个指令的地址外,也将参数、区域变量等数据存入堆栈中
- 表达式的转换与求值
- 二叉树的遍历
- 图形的深度优先(depth-first)搜索算法
四、数组模拟栈
class ArrayStack{
private int maxSize;
private int[] stack;
private int top=-1;
/**
* 构造器
* @param maxSize
*/
public ArrayStack(int maxSize){
this.maxSize=maxSize;
this.stack=new int[this.maxSize];
}
/**
* 判断栈是否满
* @return
*/
public boolean isEmpty(){
return top==-1;
}
/**
* 判断是否为空
* @return
*/
public boolean isFull(){
return top==maxSize-1;
}
/**
* 压栈
* @param value
*/
public void push(int value){
if(isFull()){
System.out.println("栈满!");
return;
}else{
top++;
stack[top]=value;
}
}
/**
* 出栈
* @return
*/
public int pop(){
if(isEmpty()){
throw new RuntimeException("栈为空!");
}
int value=stack[top];
top--;
return value;
}
/**
* 遍历
*/
public void display(){
if(isEmpty()){
System.out.println("栈为空!");
return;
}
for (int i = top; i >=0 ; i--) {
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
}