一、栈的概念
- 栈是一种只允许在一端进行插入和删除的线性表,它是一种操作受限的线性表。
- 在表中只允许进行插入和删除的一端称为栈顶(top)。另一端称为栈底(bottom)。
- 栈的插入操作称为入栈或者进栈(push)。栈的删除操作称为出栈或者退栈(pop)。
- 当栈中无数据时,我们称为空栈。
- 栈的特点:先进后出。!
二、栈的顺序存储结构
java实现代码
class SqStack{
private int []stack;//定义栈
private int top;//栈顶
//初始化栈
public SqStack(){
this.stack=new int[10];
this.top=0;
}
public SqStack(int size){
this.stack=new int[size];
this.top=0;
}
//入栈,首先先判断是否满,如果满了,扩容!然后赋值。
public void push(int val){
if(full())
resize();
this.stack[this.top++]=val;
}
//出栈,首先先判断是否空,如果空,直接return!
public void pop(){
if(empty())
return;
this.top--;
}
//栈顶
public int top(){
return this.stack[this.top-1];
}
//判空
public boolean empty(){
return this.top == 0;
}
//判满
public boolean full(){
return this.top==this.stack.length;
}
//栈的扩容,一次扩容2倍
public void resize(){
this.stack=Arrays.copyOf(this.stack,this.stack.length*2);
}
}
//main实现代码测试
public class TestStackDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
SqStack s1= new SqStack();
for (int i=0; i<20; i++ ){
s1.push((int)(Math.random()*100));
}
while(!s1.empty()){
System.out.printf("%d ",s1.top());
s1.pop();
}
}
}
- 注意:
- 对于顺序栈,入栈时,首先判断是否满了,栈满的条件是top==stack.length;满了就要想办法扩容。
- 出栈和读栈顶元素操作时,先判断是否为空,为空时不能操作,否则会产生错。
三、栈的链式存储结构
- 为避免栈上溢,更好的办法是使用链式存储结构,让多个栈共享所有可用存储空间。所以,栈也可以采用链式存储结构表示,这种结构的栈简称为链栈。
java实现代码
//首先定义一个节点
class Node{
int value;
Node next;
Node(){
this(0);
}
//对节点初始化
Node(int value){
this.value= value;
this.next = null;
}
}
//定义一个链栈
class LinkStack{
Node bottom;//栈底
Node top;//栈顶
//对栈底和栈顶初始化
public LinkStack(){
top=bottom = new Node(0);
}
//入栈操作,还是先定义一个节点,然后头节点更新一下。
public void push(int val){
Node node = new Node(val);
node.next=this.top;
this.top=node;
}
//出栈操作,判断头结点是否为空,否则更新头结点
public void pop(){
if(this.top == null){
return;
}
else{
this.top=this.top.next;
}
}
//栈顶就是top节点的值
public int top(){
return this.top.value;
}
//判空
public boolean empty(){
return this.top==this.bottom;
}
//自己设计toString()
public String toString(){
StringBuilder bulider = new StringBuilder();
Node node = this.top;
while(node != bottom){
bulider.append(node.value + " ");
node = node.next;
}
return bulider.toString();
}
函数的实现
public class TestLinkStackDemo {
public static void main(String[] args) {
LinkStack q1 = new LinkStack();
for (int i=0; i<20; i++ ){
q1.push((int)(Math.random()*100));
}
System.out.println(q1.toString());
}
}
三、单链表
Java代码
//创节点
class Node{
int value;
Node next;
Node(){
this(0);
}
//初始化节点
Node(int value){
this.value= value;
this.next = null;
}
}
//创单链表
class LinkList{
Node head;
public LinkList(){
this.head = new Node();
}
public boolean empty(){
return head==null;
}
//头插直接新建一个结点,然后更新头结点
public void insertHead(int value){
Node node = new Node(value);
node. next = head;
head = node;
}
//尾插,先将头结点给一个临时结点,然后临时结点跑到尾,然后新建结点
public void insertTail(int value){
Node ptail = head;
while(ptail.next != null){
ptail = ptail.next;
}
ptail.next = new Node(value);
}
//删除节点
public void destroy(int value){
Node pcur = head.next;
Node ppre = head;
while(pcur != null){
if(pcur.value == value){
ppre.next = pcur.next;
break;
}
ppre = pcur;
pcur = pcur.next;
}
}
public String toString(){
StringBuilder builder=new StringBuilder();
Node n=head;
while(n!=null){
builder.append(n.value+"");
n=n.next;
}
return builder.toString();
}
}
main测试代码
public class TestLinkListDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkList q1 = new LinkList();
for (int i=0; i<20; i++ ){
q1.insertHead((int)(Math.random()*100));
}
System.out.println(q1.toString());
}
}
四、顺序表和链表的比较
- 顺序表的优点如下
- (1)用数组存储数组元素,操作方法简单,容易实现。
- (2)无须为表示结点间的逻辑关系而增加额外的存储开销。
- (3)存储密度高。
- (4)顺序表可按元素位序随机存取结点。
- 顺序表的缺点如下
- 做插入、删除操作时,须大量地移动数据元素,效率比较低。
- 要占用连续的存储空间,存储分配只能预先进行。如果估计量过大,可能导致后面的大量空间闲置;如果预先分配过小,又会造成数据溢出。
- 链表和顺序表的优缺点刚好相反。
- -