char栈java,Java数据结构与算法-栈和队列(示例代码)
(摘錄加總結)------
棧和隊列不屬于基礎的數據結構,它們都屬于線性表。
一、棧
對于棧存儲操作元素只能在棧結構的一端進行元素的插入和刪除,是一種性質上的線性表結構。按照“先進后出”的原則進行存儲數據。先進的元素在棧底,后進的元素在棧頂。需要讀數據的時候從棧頂開始彈出數據(最后一個數據被第一個讀出來)。比較常規的說明是:棧底固定,而棧頂浮動;棧中元素個數為零時稱為空棧。插入一般稱為進棧(PUSH),刪除則稱為退棧(POP)。
棧的實現結構包括順序結構實現和鏈式結構實現。前者依據的是數組,后者是鏈表。
(1)利用數組實現棧
下面這個是一個基本的實現:①在Stack底層設置了一個int數組,當然可以使用泛型來指代不同的數據類型。最大容量和棧頂位置。特別需要注意的是在初始化時也看出來,一般在初始化的時候top位置設置為-1,這是利于后面在壓入數據的時候數組的第一位是array[0],并且maxSize最大容量和數組的length是一致的。②top表示這個數組的當前的沒有被設置元素的第一個位置的標志位是多少,首先要判斷是否小于maxSize-1,因為是從-1開始的,并且每次判斷都是++top,是先自增的處理,示意如下,假如初始化了一個容量為3的數組:
③當壓棧完成的時候自然top的索引值已經變成了數組最高項的值的大小,在進行pop彈棧操作的時候自然已經是完成了壓棧操作的,此時的top的值是最大位置處,所以return array[top--]就完成了彈出最大的那個元素,并且將索引top值在彈棧之后再減一。④判斷是否空棧是通過top == -1來判斷的,即初始化的情況。
public class MyStack {
private int[] array;
private int maxSize;
private int top;
public MyStack(int size){
this.maxSize = size;
array = new int[size];
top = -1;
}
//壓入數據
public void push(int value){
if(top < maxSize-1){
array[++top] = value;
}
}
//彈出棧頂數據
public int pop(){
return array[top--];
}
//訪問棧頂數據
public int peek(){
return array[top];
}
//判斷棧是否為空
public boolean isEmpty(){
return (top == -1);
}
//判斷棧是否滿了
public boolean isFull(){
return (top == maxSize-1);
}
}
(2)利用棧的后進先出的特性可以很容易的實現逆序的操作,比如下面這個利用棧實現字符串的輸入的逆序:這里使用一個用Object類型數組來接收數據,并且加入了判斷是否擴容的ArrayStack類來進行測試,實現字符串的逆序輸出:
package stack.test;
import java.util.Arrays;
import java.util.EmptyStackException;
public class ArrayStack {
// 存儲元素的數組,聲明為Object類型能存儲任意類型的數據
private Object[] elementData;
// 指向棧頂的指針
private int top;
// 棧的總容量
private int size;
// 默認構造一個容量為10的棧
public ArrayStack() {
this.elementData = new Object[10];
this.top = -1;
this.size = 10;
}
public ArrayStack(int initialCapacity) {
if (initialCapacity < 0) {
throw new IllegalArgumentException("棧初始容量不能小于0: " + initialCapacity);
}
this.elementData = new Object[initialCapacity];
this.top = -1;
this.size = initialCapacity;
}
// 壓入元素
public Object push(Object item) {
// 是否需要擴容
isGrow(top + 1);
elementData[++top] = item;
return item;
}
// 彈出棧頂元素
public Object pop() {
Object obj = peek();
remove(top);
return obj;
}
// 獲取棧頂元素
public Object peek() {
if (top == -1) {
throw new EmptyStackException();
}
return elementData[top];
}
// 判斷棧是否為空
public boolean isEmpty() {
return (top == -1);
}
// 刪除棧頂元素
public void remove(int top) {
// 棧頂元素置為null
elementData[top] = null;
this.top--;
}
/**
* 是否需要擴容,如果需要,則擴大一倍并返回true,不需要則返回false
*
* @param minCapacity
* @return
*/
public boolean isGrow(int minCapacity) {
int oldCapacity = size;
// 如果當前元素壓入棧之后總容量大于前面定義的容量,則需要擴容
if (minCapacity >= oldCapacity) {
// 定義擴大之后棧的總容量
int newCapacity = 0;
// 棧容量擴大兩倍(左移一位)看是否超過int類型所表示的最大范圍
if ((oldCapacity << 1) - Integer.MAX_VALUE > 0) {
newCapacity = Integer.MAX_VALUE;
} else {
newCapacity = (oldCapacity << 1);// 左移一位,相當于*2
}
this.size = newCapacity;
elementData = Arrays.copyOf(elementData, size);
return true;
} else {
return false;
}
}
//測試字符串輸入“drive”
public static void main(String[] args) {
String testString = "drive";
ArrayStack stack = new ArrayStack(10);
char[] cc = testString.toCharArray();
for (char c : cc) {
stack.push(c);
}
while (!stack.isEmpty()) {
System.out.print(stack.pop());
}
}
}
運行結果:
(3)這里在記錄一個利用棧的原理來進行分隔符匹配:(摘錄)
//分隔符匹配
//遇到左邊分隔符了就push進棧,遇到右邊分隔符了就pop出棧,看出棧的分隔符是否和這個有分隔符匹配
@Test
public void testMatch(){
ArrayStack stack = new ArrayStack(3);
String str = "12";
char[] cha = str.toCharArray();
for(char c : cha){
switch (c) {
case ‘{‘:
case ‘[‘:
case ‘
stack.push(c);
break;
case ‘}‘:
case ‘]‘:
case ‘>‘:
if(!stack.isEmpty()){
char ch = stack.pop().toString().toCharArray()[0];
if(c==‘}‘ && ch != ‘{‘
|| c==‘]‘ && ch != ‘[‘
|| c==‘)‘ && ch != ‘(‘){
System.out.println("Error:"+ch+"-"+c);
}
}
break;
default:
break;
}
}
}
棧操作所耗的時間不依賴棧中數據項的個數。
二、隊列
隊列區別于棧的最主要的特性就是“先進先出”。隊列只允許在隊列的前端(front)進行刪除操作,即隊頭進行刪除,在隊列的后端(rear)進行插入操作,即隊尾進行插入操作。這樣子理解其實就類似于排隊一樣和名字一樣,從隊尾插入的數據是最先進入的,所以會一直“排”到隊頭的位置去,而刪除操作是從隊頭的位置開始刪除的,所以滿足先進先出,示意:
隊列的分類也有兩種:單向隊列(Queue)和雙向隊列(Deque):主要是操作插入元素和刪除元素的位置的不同導致的。實現方式也包括數組實現和鏈表實現。
(1)單向隊列實現---(摘錄和總結)
與棧不同的是,隊列中的數據不總是從數組的0下標開始的,移除一些隊頭front的數據后,隊頭指針會指向一個較高的下標位置。也就是說與初始化的整體容量相比沒有完全滿溢的情況下,會出現下圖所示的情況。一般隊頭指針在刪除掉元素之后會向上移動,隊尾指針在插入元素之后也會向上移動,這樣子如果在刪除掉一些隊頭元素之后再插入元素就會出現容量溢出的情況,這樣子是不好的。
所以為了解決隊列不滿而不能插入新的元素所以引入了“循環隊列”的概念。即讓隊尾指針繞到隊頭的位置。
具體實現:
public class MyQueue {
private Object[] queArray;
//隊列總大小
private int maxSize;
//前端
private int front;
//后端
private int rear;
//隊列中元素的實際數目
private int nItems;
public MyQueue(int s){
maxSize = s;
queArray = new Object[maxSize];
front = 0;
rear = -1;
nItems = 0;
}
//隊列中新增數據
public void insert (int value) {
if (!isfull()) {
if (rear == maxsize - 1) {
rear = -1;
}
quearray[++rear] = value;
items++;
}
else
System.out.println("隊列已經滿了.");
}
//移除數據
public Object remove(){
Object removeValue = null ;
if(!isEmpty()){
removeValue = queArray[front];
queArray[front] = null;
front++;
if(front == maxSize){
front = 0;
}
nItems--;
return removeValue;
}
return removeValue;
}
//查看隊頭數據
public Object peekFront(){
return queArray[front];
}
//判斷隊列是否滿了
public boolean isFull(){
return (nItems == maxSize);
}
//判斷隊列是否為空
public boolean isEmpty(){
return (nItems ==0);
}
//返回隊列的大小
public int getSize(){
return nItems;
}
}
(2)優先級隊列(專用數據結構)
在優先級隊列中,數據項按照關鍵字進行排序,關鍵字最小(或者最大)的數據項往往在隊列的最前面,而數據項在插入的時候都會插入到合適的位置以確保隊列的有序。每個元素都有一個優先權。
處理方法:一般情況下,①查找操作用來搜索優先權最大的元素,②刪除操作用來刪除該元素 。③對于優先權相同的元素,可按先進先出次序處理或按任意優先權進行。
可用數組來實現優先級隊列也可以用堆來實現,速度更快。數組實現優先級隊列,聲明為int類型的數組,關鍵字是數組里面的元素,在插入的時候按照從大到小的順序排列,也就是越小的元素優先級越高。
同理nItems表示當前隊列里面已經插入好了的元素,當然按照插入原則這nItems個元素在隊列中肯定是按照從大到小的順序插入的。
public class PriorityQue {
private int maxSize;
private int[] priQueArray;
private int nItems;
public PriorityQue(int s){
maxSize = s;
priQueArray = new int[maxSize];
nItems = 0;
}
//插入數據
public void insert(int value){
int j;
if(nItems == 0){
priQueArray[nItems++] = value;
}else{
j = nItems -1;
//選擇的排序方法是插入排序,按照從大到小的順序排列,越小的越在隊列的頂端
while(j >=0 && value > priQueArray[j]){
priQueArray[j+1] = priQueArray[j];
j--;
}
priQueArray[j+1] = value;
nItems++;
}
}
//移除數據,由于是按照大小排序的,所以移除數據我們指針向下移動
//被移除的地方由于是int類型的,不能設置為null,這里的做法是設置為 -1
public int remove(){
int k = nItems -1;
int value = priQueArray[k];
priQueArray[k] = -1;//-1表示這個位置的數據被移除了
nItems--;
return value;
}
//查看優先級最高的元素
public int peekMin(){
return priQueArray[nItems-1];
}
//判斷是否為空
public boolean isEmpty(){
return (nItems == 0);
}
//判斷是否滿了
public boolean isFull(){
return (nItems == maxSize);
}
}
insert() 方法,先檢查隊列中是否有數據項,如果沒有,則直接插入到下標為0的單元里,否則,從數組頂部開始比較,找到比插入值小的位置進行插入,并把 nItems 加1。remove 方法直接獲取頂部元素。優先級隊列此處的優先級的體現是元素的大小的順序,大的元素的優先級別更高,主要是在插入元素的時候體現的。
總結
以上是生活随笔為你收集整理的char栈java,Java数据结构与算法-栈和队列(示例代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php exchange,PHP SDK
- 下一篇: php redis删除所有key,PHP