数据结构(五)--栈和队列、输出n个元素的全排列(递归算法)

特殊的线性表–栈和队列

1.栈:插入和删除操作只允许在线性表的一端进行。(栈是操作系统实现嵌套调用机制的基础)

栈顶允许操作的一端
栈底不允许操作的一端
入栈(push)往栈中插入元素
出栈(pop)删除栈中元素
栈顶元素(peek)返回栈顶元素(未出栈)

注:顺序栈–入出栈采用插入、删除,时间复杂度为O(1),自动扩充容量时入栈为O(n);
链式栈–入出栈采用插入、删除,时间复杂度为O(1)

2.使用栈计算算术表达式的值
思路:利用栈的特性将中缀表达式转换成后缀表达式

package Stack;
import java.util.Stack;
public class Expression { 
	public static StringBuffer toPostfix(String infix) { 
     stack <String>stack=new SeqStack<String>(infix.length());
     StringBuffer postfix=new StringBuffer(infix.length()*2);
     System.out.println(253);
     int i=0;
     while(i<infix.length()) { 
    	 char ch=infix.charAt(i);
    	 switch(ch) { 
    	    case'+':
    	    case'-':         //只有栈空或栈顶为“(”时入栈
    	    	while(!stack.isEmpty()&&!stack.peek().equals("("))
    	    		postfix.append(stack.pop());
    	    	stack.push(ch+"");
    	    	i++;
    	    	break;
    	    case'*':
    	    case'/':        //栈空或栈顶不为“*”“/”时入栈
    	    	while(!stack.isEmpty()&&(stack.peek().equals("*")||stack.peek().equals("/")))
    	    		postfix.append(stack.pop());
    	    	stack.push(ch+"");
    	    	i++;
    	    	break;
    	    case'(':
    	    	stack.push(ch+"");
    	    	i++;
    	    	break;
    	    case')':
    	    	String out=stack.pop();
    	    	while(out!=null&&!out.equals("(")) { 
    	    		postfix.append(out);
    	    		out=stack.pop();
    	    	}
    	    	i++;
    	    	break;
    	    default:         //遇到数字时的处理
    	    	while(i<infix.length()&&ch>='0'&&ch<='9') { 
    	    		postfix.append(ch);
    	    		i++;
    	    		if(i<infix.length()) { 
    	    			ch=infix.charAt(i);
    	    		}
    	    	}
    	    	postfix.append(" "); //添加空格作为数值之间的分隔符
    	 }
     }
     
     while(!stack.isEmpty()) {                                                            //所有运算符出栈
    	 postfix.append(stack.pop());
     }	
     return postfix;                                                                         //返回后缀表达式
	}
	
//计算后缀表达式的值
	public static int toValue(StringBuffer postfix) { 
		stack<Integer>stack=new LinkedStack<Integer>();
		System.out.println(1783);
		int value=0;
		for(int i=0;i<postfix.length();i++) { 
			char ch=postfix.charAt(i);
			if(ch>='0'&&ch<='9') { 
				value=0;
				while(ch!=' ') {                                                               //判别是否为空格间隔符, 将整数字符串转化为整数值 
					value=value*10+ch-'0';	
					ch=postfix.charAt(++i);  //读取下一个字符
			    }
				stack.push(value);
		   }
			else if(ch!=' ') { 
				int y=stack.pop(),x=stack.pop();  //出栈两个操作数,出栈顺序
				
				switch(ch) { 
				case'+':
					value=x+y;
				    break;
				case'-':
					value=x-y;
				    break;
				case'*':
					value=x*y;
				    break;
				case'/':
					value=x/y;
				    break;
				}
				System.out.print(x+(ch+"")+y+"="+value+", ");
				stack.push(value);
			}
		}
		return stack.pop();
	}
	public static void main(String args[]) { 
		String infix="123+10*(45-50+20)/((35-25)*2+10)-11";
		StringBuffer postfix=toPostfix(infix);
		System.out.println(123);
		System.out.println("infix="+infix+"\npostfix="+postfix+"\nvalue="+toValue(postfix));
	}
}
	

3.队列:插入和删除操作分别在线性表的两端进行。

队尾允许入队的一端
队头允许出队的一端
入队(add)往队中插入元素
出队(poll)删除队中元素
队头元素(peek)返回队头元素(未出栈)

注:顺序队列–使用顺序表,出队效率低;使用数组,会存在假溢出(即下标越界并不是因为存储空间不够)
顺序循环队列–队列空条件:frontnear;队列满的条件(此时,队列中仍有一个空位置):front(rear+1)%length(front是队头元素下标,rear是下一个入队元素下标,取值为0~length-1)

front=(front+1)%length;
rear=(rear+1)%length;

链式队列–入队效率低(单链表尾插),占用较多存储空间(循环双链表)

4.递归算法
输出n个元素的全排列
如:{1,2,3}的全排列为123,132,213,231 ,312,321

/* * 输出n个元素的全排列(可指定从第几个开始后面的元素全排列) */
package Queue;
import java.util.Scanner;
public class Test4_10 { 
      public static void Test4_10(int[]list,int start,int length) { 
    	  int i;
    	  if(start==length) { 
    		  for(i=0;i<length;i++) 
    			  System.out.print(list[i]+"");
    		  System.out.println();
    	  }
    	  else { 
    		  for(i=start;i<length;i++) {             //进行递归
    			  swap(list,start,i);
    			  Test4_10(list,start+1,length);
    			  swap(list,start,i);
    		  }
    	  }
      }
      public static void swap(int[]list,int start,int i) {   //两数交换位置
    	  int temp;
    	  temp=list[start];
    	  list[start]=list[i];
    	  list[i]=temp;
      }
      
      public static void main(String[]args) { 
    	  System.out.println("请输入要进行全排列的元素个数:");
    	  Scanner scanner=new Scanner(System.in);
    	  int length=scanner.nextInt();
    	  System.out.println("请输入要进行全排列的元素:");
    	  
    	  int start=0;// 表示从第start+1个后面的元素开始全排列,前面的保持不变
    	  int []list=new int[length];
    	  for(int j=0;j<length;j++) { 
    		  int num=scanner.nextInt();
    		  list[j]=num;
    	  }
    	  System.out.println("这"+length+"个元素的全排列结果为:");
    	  Test4_10(list,start,length);
      }
}

    原文作者:grape_111
    原文地址: https://blog.csdn.net/weixin_43839339/article/details/88358065
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞