一、 实验目的:
1. 深入了解栈的存储结构和运算特点。
2. 熟练掌握栈的基本运算。
3. 深入了解队列的特性。
4. 掌握队列的两种存储结构和运算方法。
二、 实验内容:
1. 栈:
分别使用顺序栈和链栈各完成以下栈的应用之一。
(1) 括号匹配问题。判断一个表达式中所含有多种括号是否匹配。
(2) 判断回文。 判断一个字符串的内容是否是回文
(3) 数制转换问题。将一个十进制数转换为十六进制形式输出。
例:26 转换为 1A
(4) 大数加法问题。将两个用字符串表示的大数,进行加法运算,并保存为和字符串。
2. 队列:
(1) 分别实现队列的顺序存储结构(循环队列),队列的链式存储结构。
(2) (选做)运用队列实现打印杨辉三角。
(1) 括号匹配问题。判断一个表达式中所含有多种括号是否匹配。
使用顺序栈解决:
接口Istack:
接口Istack:
package ch03;
public interface Istack
{
public void clear(); //将一个已经存在的栈置为空
public boolean isEmpty();//判断栈是否为空
public int length(); //返回栈中个数据元素的个数
public Object peek();
//读取栈项元素,若栈为空,则返回为空
public void push(Object x) throws Exception;
//入栈:将数据元素压入栈顶
public Object pop(); //出栈:删除并返回栈顶元素
}
顺序栈SqStack:
package ch03;
public class SqStack implements Istack
{
private Object[]stackElem; //对象数组
private int top;
//如果栈为空,top=0,否则表示栈顶元素的下一个存储位置
//构造方法,构造一个存储空间容量为k的空栈
public SqStack(int k)
{
top = 0;
stackElem = new Object[k];
}
//栈置空
public void clear()
{
top = 0;
}
//判断栈是否为空
public boolean isEmpty()
{
return top == 0;
}
//求栈中数据元素的个数
public int length()
{
return top;
}
//取栈顶元素
public Object peek()
{
if(!isEmpty())
{
return stackElem[top-1];
}
else
return null;
}
//入栈
public void push(Object x) throws Exception
{
if(top == stackElem.length)
throw new Exception("栈已满!");
else
stackElem[top++]= x;
}
//出栈
public Object pop()
{
if(isEmpty())
return null;
else
return stackElem[--top];
/* {
top = top-1;
return stackElem[top];
}*/
}
public void display()
{
for(int i = top-1;i>=0;i--)
System.out.print(stackElem[top].toString()+" ");
}
}
测试类Example1.java:
package ch03;
import java.util.Scanner;
public class Example1
{
private final int LEFT = 0;
private final int RIGHT = 1;
private final int OTHER = 2;
//判断括号类型
public int verifyFlag(String str)
{
if("(".equals(str)||"[".equals(str)||"{".equals(str)||"/*".equals(str))
return LEFT;
else if(")".equals(str)||"[".equals(str)||"{".equals(str)||"*/".equals(str))
return RIGHT;
else
return OTHER;
}
//检验左括号与右括号是否匹配
public boolean match(String str1,String str2)
{
if("(".equals(str1)&&")".equals(str2)||"[".equals(str1)&&"]".equals(str2)||"{".equals(str1)&&"}".equals(str2)||"/*".equals(str1)&&"*/".equals(str2))
return true;
else
return false;
}
private boolean isLegal(String str) throws Exception
{
if(!"".equals(str)&&str!=null)
{
SqStack S = new SqStack(100);
int length = str.length();
for(int i=0;i<length;i++)
{
char c = str.charAt(i);
String t = String.valueOf(c);
if(i!= length)
{
if(('/') == c && '*' == str.charAt(i + 1) ||('*'==c && '/'==str.charAt(i+1)))
{
t = t.concat(String.valueOf(str.charAt(i+1)));
++i;
}
}
if(LEFT == verifyFlag(t))
{
S.push(t);
}
else if (RIGHT == verifyFlag(t))
{
if(S.isEmpty()||!match(S.pop().toString(),t))
{
throw new Exception("错误!Java语句不合法!!!");
}
}
}
if(!S.isEmpty())
throw new Exception("错误:java 语句不合法!");
return true;
}
else
throw new Exception("错误;java 语句为空!");
}
public static void main(String []args) throws Exception
{
Example1 e1 = new Example1();
System.out.println("请输入分Java语句:");
Scanner sc = new Scanner(System.in);
if(e1.isLegal(sc.nextLine()))
System.out.println("java语句合法!");
else
System.out.println("错误!Java语句不合法!");
}
}
运行结果:
(2) 判断回文。 判断一个字符串的内容是否是回文
//判断字符序列是否为回文序列,若是则返回true,否则返回false;
public Boolean isPalindSeq(String str)
{
LinkStack S = new LinkStack();
int i = 0;
for(i = 0;i< str.length;i++)
{
S.push(str.charAt(i));
char c = ((Character)S.pop().charValue();
if(c!=str.charAt(i))
return false;
}
return true;
}
(4) 使用链栈解决大数加法问题
接口Istack:
package ch01;
public interface Istack
{
public void clear(); //将一个已经存在的栈置为空
public boolean isEmpty(); //判断栈是否为空
public int length(); //返回栈中个数据元素的个数
public Object peek();
//读取栈项元素,若栈为空,则返回为空
public void push(Object x) throws Exception;
//入栈:将数据元素压入栈顶
public Object pop(); //出栈:删除并返回栈顶元素
}
结点类Node:
package ch01;
public class Node
{
public Object data;
public Node next;
public Node()
{
this(null,null);
}
public Node(Object data)
{
this(data,null);
}
public Node(Object data,Node next)
{
this.data = data;
this.next = next;
}
}
链栈LinkStack:
package ch01;
public class LinkStack implements Istack
{
private Node top;
public void clear()
{
top = null;
}
public boolean isEmpty()
{
return top == null;
}
public int length()
{
Node p = top;
int length = 0;
while(p != null)
{
p = p.next;
++length;
}
return length;
}
//取栈顶元素并返回其值
public Object peek()
{
if(!isEmpty())
return top.data;
else
return null;
}
//入栈
public void push(Object x)
{
Node p = new Node(x);
p.next = top;
top = p;
}
//出栈
public Object pop()
{
if(isEmpty())
{
return null;
}
else
{
Node p = top;
top = top.next;
return p.data;
}
}
public void display()
{
Node p = top;
while(p!= null)
{
System.out.println((p.data.toString() + " "));
p = p.next;
}
}
}
Example2:
package ch03;
public class Example2
{
public String add(String a,String b) throws Exception
{
LinkStack sum = new LinkStack();
LinkStack sA = numSplit(a);
LinkStack sB = numSplit(b);
int Sum;
boolean isCarry = false;
while(!sA.isEmpty()&&!sB.isEmpty())
{
Sum = (Integer)sA.pop() + (Integer)sB.pop();
if(isCarry)
{
Sum ++;
isCarry = false;
}
if(Sum>=10)
{
Sum =Sum-10;
sum.push(Sum);
isCarry = ture;
}
else
{
sum.push(Sum);
}
}
LinkStack temp = !sA.isEmpty()?sA:sB;
while(!temp.isEmpty())
{
if(isCarry)
{
int t = (Integer)temp.pop();
++t;
if(t>=10)
{
t = t-10;
sum.ppush(t);
}
else
{
sum.push(t);
isCarry = false;
}
}
else
sum.push(temp.pop());
}
if(isCarry)
{
sum.push(1);
}
String str = new String();
while(!sum.isEmpty())
str = str.concat(sum.pop().toString());
return str;
}
public LinkStack numSplit(String str) throws Exception
{
LinkStack s = new LinkStack();
for(int i=0;i<str.length();i++)
{
char c = str.charAt(i);
if(' ' == c)
continue;
else if('0'<= c &&'9'>=c)
s.push(Integer.valueOf(String.valueOf(c)));
else
throw new Exception("错误:输入了非数字型字符");
}
return s;
}
public static void main(String []args) throws Exception
{
Example2 e = new Example2();
System.out.println("两个大数的和:"+ e.add("12345678","12345678"));
}
}
队列的顺序存储结构如下:
接口:IQueue
public interface IQueue
{
public void clear(); //将队列置为空队列
public boolean isEmpty(); //判断队列是否为空
public int length(); //返回队中中中数据元素的个数
public Object peek(); //读取队首元素并返其值
public void offer(Object x ) throws Exception;
//将数据元素x插入使其成为新的队尾元素
public Object poll();
//删除队首元素并返回其值,若队列为空,则返回为空
}
定义类CircleSqQueue实现接口:
public class CircleSqQueue implements IQueue
{
private Object[]Elem;
private int front ; //队首元素
private int rear; //队尾不空,指向队尾元素的下一个存储空间
//构造方法
public CircleSqQueue(int maxSize)
{
front = rear = 0;
Elem = new Object[maxSize];
}
public void clear()
{
front = rear = 0;
}
public boolean isEmpty()
{
return front == rear ;
}
public int length()
{
return (rear -front+Elem.length)%Elem.length;
}
public Object peek()
{
if(front == rear )
return null;
else
return Elem[front];
}
public void offer (Object x) throws Exception
{
if((rear +1 )%Elem.length == front )
throw new Exception("队列已满!");
else
{
Elem[rear] = x;
rear =(rear + 1) % Elem.length;
}
}
public Object poll()
{
if(front == rear)
return null;
else
{
Object t = Elem[front];
front = (front + 1) % Elem.length;
return t;
}
}
public void display()
{
if(!isEmpty())
{
for(int i = front;i!=rear; i = (i+1)%Elem.length)
System.out.println(Elem[i].toString() + " ");
}
else
System.out.println("此队列为空!");
}
}
队列的链式存储结构如下:
结点类Node:
package ch01;
public class Node
{
public Object data;
public Node next;
public Node (Object data,Node next)
{
this.data = data;
this.next = next;
}
public Node()
{
this(null,null);
}
public Node(Object data)
{
this(data,null);
}
}
IQueue接口:
package ch01;
public interface IQueue
{
public void clear(); //将队列置为空队列
public boolean isEmpty(); //判断队列是否为空
public int length(); //返回队中中中数据元素的个数
public Object peek(); //读取队首元素并返其值
public void offer(Object x ) throws Exception;
//将数据元素x插入使其成为新的队尾元素
public Object poll();
//删除队首元素并返回其值,若队列为空,则返回为空
}
LinkQueue类:
package ch01;
import ch01.Node;
public class LinkQueue implements IQueue
{
private Node front;
private Node rear;
public LinkQueue()
{
front = rear = null;
}
public void clear()
{
front =rear = null;
}
public boolean isEmpty()
{
return front == null;
}
public int length ()
{
Node p = front;
int length = 0;
while(p != null)
{
p = p.next;
++length;
}
return length;
}
public Object peek()
{
if(front != null)
return front.data;
else
return null;
}
public void offer(Object x)
{
Node p = new Node(x);
if(front!=null)
{
rear.next = p;
rear = p;
}
else
front = rear = p;
}
public Object poll()
{
if(front != null)
{
Node p = front;
front =front.next;
if(p == rear)
rear = null;
return p.data;
}
else
return null;
}
}