练习题——栈与队列

十、数制转换

void Conversion(int N)  /*对于任意的一个非负十进制数N,打印出与其等值的二进制数*/
{  
      LinkStack S; int x;      /*S为顺序栈或链栈*/
      InitStack(&S);
	while(N>0)
	{   x=N%2; Push(&S, x); N=N/2; }
	while(!IsEmpty(S))
	{   Pop(&S,&x); printf(%d”,x);   }
}

十一、括号匹配问题

思想:在检验算法中设置一个栈
(1)若读入的是左括号,则直接入栈,等待相匹配的同类右括号。
(2)若读入的是右括号,且与当前栈顶的左括号同类型,则二者匹配,将栈顶的左括号出栈,否则属于不合法的情况。
(3)如果输入序列已读尽,而栈中仍有等待匹配的左括号;或者读入了一个右括号,而栈中已无等待匹配的左括号,均属不合法的情况。
(4)当输入序列和栈同时变为空时,说明所有括号完全匹配。

void BracketMatch(char *str)
{
     StackLink S; int i; char ch;
     InitStack(&S);
     for(i=0; str[i]!='\0'; i++) 
     {
         switch ( str[i] )
        {  
            case '(':
            case '[':
            case '{':  Push( &S, str[i] ) ; break;
            case ')':
       		case ']':
       		case '}':   
       					if( IsEmpty(S) )
                      { printf("\n右括号多余!");  return;}
                      else
                      { 
                            GetTop (&S,&ch);
                            if(Match(ch,str[i]))  Pop(&S,&ch); 
                            else { printf("\n对应的左右括号不同类!");
                             return;
                       }
                       }
     }/*switch*/
}/*for*/
		if(IsEmpty(S))
     		 printf("\n括号匹配!");
  		else
     		printf("\n左括号多余!");
}
int Match(char ch1,char ch2)
{
    switch(ch1)
    {
         case '(': if(ch2==')') return 1;
         case '[': if(ch2==']') return 1;
         case '{': if(ch2=='}') return 1;
         default: return 0;
     }
     return 0;
} 

十二、表达式求值

(1) 无括号算术表达式求值
表达式运算及运算符优先级
3+4*5 # ± */ **
① 0 1 2 3

无括号算术表达式的处理过程如图
(2) 算术表达式处理规则
规定优先级表;
设置两个栈:OVS(运算数栈)和OPTR(运算符栈);
自左向右扫描,遇操作符则与OPTR栈顶优先级比较:当前操作符>OPTR栈顶则进OPTR栈;
当前操作符≤ OPTR栈顶,OVS栈顶、次顶和OPTR栈顶退栈,形成运算T(i), T(i)进OVS栈。
在这里插入图片描述
(3) 带括号算术表达式
实现算符优先算法时需要使用两个工作栈:一个称作运算符栈operator;另一个称作操作数栈operand。
算法的基本过程如下:
A.初始化操作数栈operand和运算符栈operator,并将表达式起始符“#”压入运算符栈;
B.读入表达式中的每个字符,若是操作数则直接进入操作数栈operand,若是运算符,则与运算符栈operator的栈顶运算符进行优先权比较,并做如下处理:
若栈顶运算符的优先级低于刚读入的运算符,则让刚读入的运算符进operator栈;
若栈顶运算符的优先级高于刚读入的运算符,则将栈顶运算符退栈,送入θ,同时将操作数栈operand退栈两次,得到两个操作数a、b,对a、b进行θ运算后,将运算结果作为中间结果推入operand栈;
若栈顶运算符的优先级与刚读入的运算符的优先级相同,说明左右括号相遇,只需将栈顶运算符(左括号)退栈即可。当operator栈的栈顶元素和当前读入的字符均为“#”时,说明表达式起始符“#”与表达式结束符“#”相遇,整个表达式求值完毕。

十三、打印杨辉三角形

void YangHuiTriangle(int N)
{
    int n, i, x, temp;
    SeqQueue Q;
    InitQueue(&Q);
    EnterQueue(&Q,1);//第一行元素入队
    for(n=2;n<=N;n++)
    {
   		EnterQueue(&Q, 1);//入队列
   		for(i=1;i<=n-2;i++)
   		{
       		DelQueue(&Q, &temp);//出队列的数据赋给temp
      		printf("%d ", temp);
       		GetHead(&Q, &x);
       		temp=temp+x;
      	 	EnterQueue(&Q, temp);
    	}
	      DelQueue(&Q, &x);//出队列
	      printf("%d ", x);
	      EnterQueue(&Q, 1);
	      printf("\n");
	} 
	while (!IsEmpty(&Q))
   {
        DelQueue(&Q, &x);
        printf("%d ", x);
    }
}

十四、键盘输入循环缓冲区

void main()
{//模拟键盘输入循环缓冲区
    char ch1,ch2;
    SeqQueue Q; 
    int f;
    InitQueue(&Q);
    for(;;)
    {
       for(;;) //第1个进程
       {
           printf("A");
           if(kbhit())
      	{
          ch1=getch();
          if(ch1==';'||ch1==',') break; //第1个进程正常中断
          f=EnterQueue(&Q,ch1);
          if(f==FALSE)  //循环队列满时强制中断第1个进程
          {
              printf("循环队列已满!\n");
              break;
          }
        }//end if
    }//end for
    while(!IsEmpty(&Q)) //第2个进程
      {
          DelQueue(&Q,&ch2);
          putchar(ch2);  //显示输入缓冲区的内容
       }
       if(ch1==';')break;
   }//end for
}

十五、挂号看病

void SeeDoctor()
{
  LinkQueue Q;
  int flag;
  InitQueue(&Q);	
  flag=1;
  while(flag)
  {
	printf("\n请输入命令:");
	ch=getch();
	switch(ch)
	{
 	    case 'a':printf("\n病历号:");
                            scanf("%d",&n);
  		     EnterQueue(&Q,n);
		     break; 
	    case 'n':if(!IsEmpty(&Q)){
  		        DeleteQueue(&Q,&n);
		        printf("\n病历号为%d的病人就诊",n);
 		     }
  		     else	
 		        printf("\n无病人等候就诊"); 
		        break; 
	  case 'q':printf("\n今天停止挂号,下列病人依次就诊:\n");
  		   while(!IsEmpty(&Q))
		   {
		        DeleteQueue(&Q,&n);
		        printf("%d\n",n);
  		    }
 		    flag=0;
		    break; 
	  default:printf("\n非法命令!");
       }
   }
}

十六、求两个集合的差

1.已知:以单链表表示集合,假设集合A用单链表LA表示,集合B用单链表LB表示,设计算法求两个集合的差,即A-B。
2.算法思想:由集合运算的规则可知,集合的差A-B中包含所有属于集合A而不属于集合B的元素。具体做法是,对于集合A中的每个元素e,在集合B的链表LB中进行查找,若存在与e相同的元素,则从LA中将其删除。
3.算法实现

void  Difference (LinkList LA,LinkList LB) /*此算法求两个集合的差集*/
{ 
    Node  *pre;*p, *r;
    pre=LA; p=LA->next;  /*p向表中的某一结点,pre始终指向p的前驱*/
    while(p!=NULL)
    {  q=LB->next;  /*扫描LB中的结点,寻找与LA中*P结点相同的结点*/
        while (q!=NULL && q->data!=p->data)  q=q->next;
        if (q!=NULL)
       {  r=p;  pre->next=p->next;  p=p->next;  free(r); }
       else 
       { pre=p;  p=p->next; } 
    }
}

十七、双向链表应用举例

1.已知:设一个循环双链表L=(a,b,c,d)编写一个算法将链表转换为L=(b,a,c,d)。
2.算法思想:实际上是交换表中前两个元素的次序。
3.算法实现:

void swap(DLinkList L)
{ DNode *p,*q,*h;
  h=L->next;   	/* h指向表中的第一个结点,即a */
  p=h->next;   	/* p指向b结点 */
  q=h->prior;   	/* 保存a结点的前驱 */
  h->next=p->next; 
  p->next->prior=h; /*变换指针指向*/
  p->prior=q; p->next=h; 
  L->next=p;	
}

十八、一元多项式的表示及相加

一个一元多项式Pn(x)可按升幂的形式写成:Pn(x)=p0+p1x+p2x2+p3x3+ … +pnxn
在计算机内,可以用一个线性表P来表示: P=(p0,p1,p2, …,pn)
用单链表存储多项式的结点结构如下:

typedef struct Polynode 
	  {
         int coef;  /* 系数 */
         int exp;   /* 指数 */
         Polynode *next;
      } Polynode , * Polylist; 

建立多项式链表
算法描述:输入多项式的系数和指数,用尾插法建立一元多项式的链表。

Polylist  polycreate()
{  Polynode *head, *rear, *s; 	 int c,e;
   rear=head =(Polynode *)malloc(sizeof(Polynode));  
	                         /*建立多项式的头结点,rear 始终指向单链表的尾*/
   scanf(%d,%d”,&c,&e);       /*键入多项式的系数和指数项*/
   while(c!=0)	                         /*若c=0,则代表多项式的输入结束*/
   {  s=(Polynode*)malloc(sizeof(Polynode));	/*申请新的结点*/
      s->coef=c ; s->exp=e ;rear->next=s ;	/*在当前表尾做插入*/
      rear=s; scanf(%d,%d”,&c,&e);   /*按照指数从小到大输入*/
    }
    rear->next=NULL;       /*将表的最后一个结点的next置NULL,以示表结束*/
    return(head);
}

十九、两个多项式相加

运算规则:两个多项式中所有指数相同的项的对应系数相加,若和不为零,则构成“和多项式”中的一项;所有指数不相同的项均复制到“和多项式”中。
若pa->exp < pb->exp,则结点pa所指的结点应 是“和多项式”的一项,令指针pa后移;
若pa->exp > pb->exp,则结点pb所指的结点应是“和多项式”中的一项,将结点pb插入在结点pa之前,且令指针pb在原来的链表上后移;
若pa->exp = pb->exp,则将两个结点中的系数相加,当和不为零时修改结点pa的系数域,释放pb结点;若和为零,则和多项式中无此项,释放pa和pb结点。
在这里插入图片描述

void PolyAdd(Ploylist  La, Ploylist  Lb) 
{   
    Ploynode   *pa , *pb ,*tail,*temp ;     float x ;
pa=La->next ; pb=Lb->next ; tail=La;
while ( pa!=NULL && pb!=NULL )
{  if  (pa->exp < pb->exp)
   {  tail->next=pa ; tail=pa ; pa=pa->next ;    }
       /*  将pa所指的结点合并,pa指向下一个结点  */
else if  (pa->exp > pb->exp)
   {  tail->next=pb ; tail=pb ;  pb=pb->next ;    }
        /*  将pb所指的结点合并,pb指向下一个结点  */
        else
    {  x=pa->coef+pb->coef ;
        if  (abs(x)<=1.0e-6)                   /*  如果系数和为0,删除两个结点  */
        {  
                temp=pa ; pa=pa->next ;  free(temp) ;
                temp=pb ; pb=pb->next ;  free(temp) ;  
         }    
          else       /*  如果系数和不为0,修改其中一个结点的系数域,删除另一个结点  */ 
          {   
                 tail->next=pa ; pa->coef=x ;
                 tail=pa ; pa=pa->next ;
                 temp=pb ; pb=pb->next ; free(pb) ;   
          }
          }
}     /* end of while */ 
if  (pa==NULL)  tail->next=pb ;
else  tail->next=pa ;
}

二十、单链表的就地逆置

void Reverse (LinkList L)
{
  Node *p,*q;               /* p为工作指针,r为p的后继以防断链 */
  p=L->next;                  /* 从第一个元素结点开始 */
  L->next=NULL;           /* 先将头结点L的next域置为NULL */
  while(p!=NULL)         /* 依次将元素结点摘下 */
  {
      q=p->next;             /* 暂存p的后继 */
      p->next=L->next;       /* 将p结点插入到头结点之后 */
      L->next=p;
      p=q;
  }
}

二十一、从顺序表L中删除所有值为x的元素

void delx(SeqList *L, int x)    //删除所有值为x的元素
{   
     int i = 0; int j = 0;
     while (i <= L->last)
     { 
           if (L->elem[ i ] != x)
              {  L->elem[ j ] = L->elem[ i ];  i++;  j++;  }
           else 
               i++;
     }
     L->last = j - 1;
     printf("creat last=%d\n", L->last);
}

二十二、汉诺塔

void hanoi(int n,char x,char y,char z)
{
	if(n==1)
		move(x,1,z);//将编号为1的圆盘从x移到z
	else
	{
		hanoi(n-1,x,z,y);//将x上编号为1至n-1的圆盘移到y,z作辅助塔
		move(x,n,z);//将编号为n的圆盘从x移动到z
		hanoi(n-1,y,x,z);//将y上编号为1至n-1的圆盘移到z,x作辅助塔
	}
}

二十三、八皇后问题

二十四、停车场管理系统

二十五、迷宫

这道题的代码暂时不完整

struct
{
	int i;//当前方块的行号
	int j;//当前方块的列号
	int di;//下一可走的方块
}Stack[MaxSize];//定义栈
int top=-1;//初始化栈
void mgpath()//路径为(1,1)->(M-2,N-2)
{
	int i,j,di,find,k;
	top++;//初始方块进栈
	Stack[top].i=1;
	Stack[top].j=1;
	Stack[top].di=-1;
	mg[1][1]=-1;
	while(top>-1)//栈不空时循环
	{
		i=Stack[top].i;
		j=Stack[top].j;
		di=Stack[top].di;
		if(i=M-2&&j=N-2)//找到了出口,输出路径
		{
			printf("迷宫路径如下:")
			for(k=0;k<=top;k++)
			{
				printf("\t(%d%d)",Stack[k].i,Stack[k].j);
				if((k+1)%5==0)
					printf("\n");
					return;
			}
			find=0;
			while(di<4&&find==0)//找下一个可走方块
			{
				d++;
				switch(di)
				{
					//往上走
					case 0:
						i=Stack[top].i-1;
						j=Stack[top].j;
						break;
					//往右走
					case 1:
						i=Stack[top].i;
						j=Stack[top].j+1;
						break;
					//往下走
					case 2:
						i=Stack[top].i+1;
						j=Stack[top].j;
						break;
					//往左走
					case 3:
						i=Stack[top].i;
						j=Stack[top].j-1;
						break;
				}
				if(mg[i][j]==0)
					find=1;
			}
			if(find==1)//找到了下一个可走方块
			{
				Stack[top].di=di;//修改原栈顶元素di值
				top++;//下一个可走方块进栈
				Stack[top].i=i;
				Stack[top].j=j;
				Stack[top].di=-1;
				mg[i][j]=-1;//避免重复走到该方块
			}
			else//没有路径可走,则退栈
			{
				mg[Stack[top].i][Stack[top].j]=0;//让该位置变为其他路径可走方块
				top--;
			}
		}
		printf("没有可走路径\n");
	}

二十六、使用顺序栈实现十进制整数到r进制(2<=r<=8)的转换。

#include<stdlib.h>
#include<stdio.h>
#include<stddef.h>
/*定义栈结构*/
typedef struct
{
    char data[50];
    int top;
}SeqStack,*PSeqStack;
/*初始化栈,构造一个空栈,如果成功,则返回栈的地址*/
PSeqStack Init_SeqStack()
{
    PSeqStack s;
    s=(PSeqStack)malloc(sizeof(SeqStack));
    if(s)
    {
        s->top=-1;
    }
    return s;
}
/* 判断栈是否为空,如果为空,则返回1,否则返回0*/
int Empty_SeqStack(PSeqStack s)
{
    if(s->top==-1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
/*入栈操作,栈不满时,入栈一个元素,成功返回1,失败返回0*/
int Push_SeqStack(PSeqStack s,char x)
{
    if(s->top==49)
    {
         return 0;
    }
    else
    {
        s->top=s->top+1;
        s->data[s->top]=x;
        return 1;
    }
}
/*出栈操作,栈不空时,出栈一个元素,用参数*x保存,成功返回1,失败返回0*/
int Pop_SeqStack(PSeqStack s,char *x)
{
    if(Empty_SeqStack(s))
    {
        return 0;
    }
    else
    {
        *x=s->data[s->top];
        s->top=s->top-1;
        return 1;
    }
}
/*取栈顶元素操作,栈不空时,获取栈顶元素,成功返回1,失败返回0*/
int GetTop_SeqStack(PSeqStack s,char *x)
{
    if(Empty_SeqStack(s))
    {
        return 0;
    }
    else
    {
        *x=s->data[s->top];
        return 1;
    }
}
/*销毁栈*/
void Destroy_SeqStack(PSeqStack *s)
{
    if(*s)
    {
        free(*s);
    }
    *s=NULL;
}
/*十进制转换成r进制(2,8,16)*/
int Conversion(int num,int r)
{
    PSeqStack s;
    char x;
    if(!r)
    {
        printf("基数不能为0");
        return -1;
    }
    s=Init_SeqStack();
    if(!s)
    {
        printf("初始化栈空间失败");
        return -1;
    }
    while(num)
    {
        if(num%r>9)
        {
            Push_SeqStack(s,num%r+'A'-10);   /*余数大于9,则进栈ABCDEF*/
        }
        else
        {
            Push_SeqStack(s,num%r+'0');   /*余数小于10,则进栈数字字符*/
            num=num/r;
        }
    }
    while(!Empty_SeqStack(s))
    {
        Pop_SeqStack(s,&x);
        printf("%c",x);
    }
    return 0;
}
int main()
{
    int r, num;
    printf("请输入一个十进制整数:");
    scanf("%d",&num);
    printf("请输入要转换成的进制:");
    scanf("%d",&r);
    Conversion(num,r);
    return 0;
}

二十七、用顺序栈判断是否为回文数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 80
//定义顺序栈结构
typedef struct
{
    char elem[MAX];
    int top;
}STACK;
void Init_Stack(STACK *pS)
{
    pS->top = -1; //top为栈顶元素在数组elem中的下标,由于开始没有元素,则为-1
}
int Push(STACK *pS, char e)
{
    if(pS->top >= MAX-1)
        return 0;
    pS->top++;  //改变栈顶位置
    pS->elem[pS->top] = e;
    return 1;
}
int Pop(STACK *pS, char *pe)
{
    if(pS->top == -1)
        return 0;
    *pe = pS->elem[pS->top];
    pS->top--;
    return 1;
}
int main()
{
    char str[80], c1,c2,*p;
    STACK S;
    int len,i=1;
    int len1;
    int sign=0;
    Init_Stack(&S);
    printf("请输入一串字符串:");
    gets(str);
    p = str;
    len=strlen(str);
    len1=strlen(str);
    if(len%2==0)len=len/2;
    else
    {
      sign=1;
      len=len/2;
    }
    //将'&'前面的字符依次入栈
    while(i<=len && *p != '\0')
    {
      if(!Push(&S, *p))
      {
        printf("栈空间溢出!");
        exit(0);
      }
      p++;
      i++;
    }
    if(sign)
    {
      p++;
    }
    //每取一个字符就和从栈中弹出的一个字符比较,如果相等
    //则继续取下一个。
    while(i<=len1 && *p != '\0')
    {
      c1 = *p;
      if(!Pop(&S, &c2))
      {
        printf("栈已为空,不是回文,'&'前面的字符少!\n");
        exit(0);
      }
      if( c1 != c2)
      {
        printf("对应字符不相等,不是回文!\n");
        exit(0);
      }
      p++;
    }
    if(Pop(&S, &c2))
    {
      printf("'&'前的字符比后面多,栈内还有字符,不是回文!\n");
      exit(0);
    }
    else
      printf("是回文!\n");
    return 0;
}

二十八、使用链栈实现含括号的算术表达式的求值(注意:运算数可为十进制的无符号整数或实数)。

该代码参考该博主的原创文章
https://blog.csdn.net/qq_43312665/article/details/103791494

#include<stdio.h>
#include<stdlib.h>
#define Stack_Init_Size 100 //栈容量
#define StackIncrement 10 //栈增量
#define OVERFLOW -1
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef char SElemType;
typedef int Status;
typedef struct SNode {
	SElemType data;
	struct  SNode* next;
}SNode, * LinkStack;
LinkStack InitStack()//注意这个初始化方式!!!!!!
{
	LinkStack s = (SNode*)malloc(sizeof(SNode));
	if (!s)
		exit(OVERFLOW);
	s->next = NULL;
	return s;
}
void Push(LinkStack s, SElemType e)
{
	LinkStack p = (SNode*)malloc(sizeof(SNode));
	if (p == NULL)
		exit(OVERFLOW);
	p->data = e;
	p->next = NULL;
	p->next = s->next;
	s->next = p;//与单链表的头插法相似
}
SElemType Pop(LinkStack s)
{
	LinkStack q;
	q = s->next;
	SElemType e = q->data;
	s->next = q->next;
	free(q);//删除单链表的第一个元素
	return e;
}
void DestroyStack(LinkStack s)
{
	free(s);
}
void ClearStack(LinkStack s)
{
	s->next = NULL;
}
Status StackEmpty(LinkStack s)
{
	if (s->next == NULL)
		return TRUE;
	else
	{
		return FALSE;
	}
}
int StackLength(LinkStack s)
{
	int i = 0;
	SNode* p = s->next;
	while (p != NULL)
	{
		i++;
		p = p->next;
	}
	return i;
}
SElemType GetTop(LinkStack l)
{
	return l->next->data;
}
void StackTravers(LinkStack s)
{
	SNode* p = s->next;
	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
}
int In(char e)//判断读入字符是否为运算符
{
	if (e == '+' || e == '-' || e == '*' || e == '/' || e == '(' || e == ')' || e == '#')
		return 1;//是
	else
		return 0; //不是
}
char Precede(char a, char b)//比较运算符的优先级
{
	char f;
	if (a == '+' || a == '-')
	{
		if (b == '+' || b == '-' || b == ')' || b == '#')
			f = '>';
		else if (b == '*' || b == '/' || b == '(')
			f = '<';
	}
	else if (a == '*' || a == '/')
	{
		if (b == '+' || b == '-' || b == '*' || b == '/' || b == ')' || b == '#')
			f = '>';
		else if (b == '(')
			f = '<';
	}
	else if (a == '(')
	{
		if (b == '+' || b == '-' || b == '*' || b == '/' || b == '(')
			f = '<';
		else if (b == ')')
			f = '=';
	}
	else if (a == ')')
	{
		if (b == '+' || b == '-' || b == '*' || b == '/' || b == ')' || b == '#')
			f = '>';
	}
	else if (a == '#')
	{
		if (b == '+' || b == '-' || b == '*' || b == '/' || b == '(')
			f = '<';
		else if (b == '#')
			f = '=';
	}
	return f;
}
char Operate(char a, char theta, char b)//运算
{
	char c;
	a = a - '0';
	b = b - '0';
	if (theta == '+')
		c = a + b + '0';
	else if (theta == '-')
		c = a - b + '0';
	else if (theta == '*')
		c = a * b + '0';
	else if (theta == '/')
		c = a / b + '0';
	return c;
}
int EvaluateExpression()
{
	LinkStack OPTR=InitStack();//寄存运算符
	Push(OPTR, '#');
	LinkStack OPND = InitStack();//寄存操作数和运算结果
	char ch, a, b, theta,x;
	ch = getchar();
	while (ch != '#' || GetTop(OPTR) != '#')
	{
		if (!In(ch))//如果不是运算符
		{
			Push(OPND, ch);
			ch = getchar();
		}
		else//如果是运算符
		{
			switch (Precede(GetTop(OPTR),ch))//比较运算符的优先级
			{
			case '<':
				Push(OPTR, ch);//刚输入的运算符优先级更高,则运算符入栈
				ch = getchar();
				break;
			case '>': //刚输入的运算符优先级更低,则进行一次运算
				theta = Pop(OPTR);//原来栈里的运算符出栈
				b = Pop(OPND);
				a = Pop(OPND);//取出两个运算数
				Push(OPND, Operate(a, theta, b));
				break;
			case '=': //输入运算符的优先级相等
				x = Pop(OPTR);
				ch = getchar();
				break;
			}
		}
	}
	return GetTop(OPND) - '0';
}
int main()
{
	printf("请输入算数表达式,以#结束\n");
	printf("例如\t 1*(2-1)# \t\n");
	printf("运行结果是:%d\n", EvaluateExpression());
	return 0;
}

二十九、使用链栈实现将含括号的中缀算术表达式转换成后缀算术表达式。(注意:运算数均为个位数)

后缀表达式(逆波兰表达式)规则:
从左到右遍历表达式的每个数字和符号,遇到是数字就入栈,遇到是符号就将处于栈顶的两个数字出栈进行运算,运算结果进栈,直到最后结果。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
	char Data;
	struct Node *Next;
}LinkStack;

LinkStack *Input;
LinkStack *CreateStack ()
{
	LinkStack *S;
	S=malloc(sizeof(struct Node));
	S->Next=NULL;
	return S;
}

int IsEmpty (LinkStack *S)
{
	return S->Next==NULL;
	printf("NULL");
}

void Push (char item ,LinkStack *S)
{
	struct Node *TmpCell;
	TmpCell=malloc(sizeof(struct Node));
	TmpCell->Data=item;
	TmpCell->Next=S->Next;
	S->Next=TmpCell;
}

char Pop (LinkStack *S)
{
	struct Node *FirstCell;
	char TopElem;
	if(IsEmpty(S))
	{
		printf("Stack is Empty!");
		return NULL;
	}
	else
	{
		FirstCell=S->Next;
		S->Next=FirstCell->Next;
		TopElem=FirstCell->Data;
		free(FirstCell);
		return TopElem;
	}
}

char Precede(char dest,char input)
{
	 char back;
	 switch(input)
	 {
	  case '+':
	  case '-': if(dest=='*'||dest=='/')
	     			back='<';
	     		else if(dest=='+'||dest=='-')   /*!!!注意考虑结合性 !!! */
	     			back='<' ;
				else
	      			back='>';
	     		break;
	  case '*':
	  case '/': if(dest=='+'||dest=='-')
	      			back='>';
	      		else if(dest=='*'||dest=='/')   /*!!!注意考虑结合性 !!! */
	      			back='=';
	     		else
	      			back='<';
	     		break;
	  default : printf(" ERROR ");
	            break;
	 }
	 return back;
}

void calculate(char input[])
{
	int i=0;
	char TopElem,PreTopElem,PrecedeResult;
	LinkStack *FirstItem;
	for(i=0;input[i]!='\0';i++)
	{
		if (input[i]>='0'&&input[i]<='9'||input[i]=='.'||input[i]>='a'&&input[i]<='z')  //输出数字部分
			printf("%c",input[i]);
		else if(input[i]=='(')  //将左括号压栈
		{
			Push (input[i] ,Input);
		}
		else if(input[i]==')')	//遇到右括号,将栈内元素弹出打印直到遇到左括号 (左括号不打印)
		{
			TopElem = Pop (Input);
			while((TopElem!='(')&&(!IsEmpty(Input)))  //一定要防止进入死循环
			{
				printf(" %c",TopElem);
				TopElem = Pop (Input);
				//printf(" #%c#",TopElem);
			}
		}
		else if(input[i]=='+'||input[i]=='-'||input[i]=='*'||input[i]=='/')
		{
			printf(" ");
			if (IsEmpty (Input)) //栈空则进栈
			{
				Push (input[i] ,Input);

			}
			else
			{
				FirstItem=Input->Next;
				if(FirstItem->Data!='(')  //栈顶元素非左括号
				{
					PrecedeResult=Precede(FirstItem->Data,input[i]); //和栈顶元素比较
					//printf("%c%c",PreTopElem,PrecedeResult);
					if(/*PreTopElem=='('&&*/PrecedeResult=='=') //结合性处理部分
					{
						TopElem = Pop (Input);
						printf("%c ",TopElem);
						Push (input[i] ,Input);
					}
					else if(PrecedeResult=='>')  //元素优先级大于栈顶元素优先级则进栈
					{
						Push (input[i] ,Input);
					}
					else //小于等于则输出Top元素,直到大于则进栈
					{
						while(!IsEmpty (Input))
						{
							TopElem = Pop (Input);
							printf("%c ",TopElem);

							if(!IsEmpty (Input))
							{
								FirstItem=Input->Next;
								PrecedeResult=Precede(FirstItem->Data,input[i]);
								//printf("%c",PrecedeResult);
							}

							if(IsEmpty (Input))
							{
								Push (input[i] ,Input);
								break;   // !!!为空进栈则陷入死循环 !!!
							}
							else if(PrecedeResult=='>')
							{
								//printf(":::>_<:::");
								Push (input[i] ,Input);
								break;
							}

						}
					}
				}
				else if(FirstItem->Data=='(') //栈顶元素是左括号则元素进栈
					Push (input[i] ,Input);
			}
		}
	}
	while(!IsEmpty (Input))
	{
		TopElem = Pop (Input);
		printf(" %c",TopElem);
	}
}
int main()
{
	char input[100];
	Input=CreateStack ();
	printf("请输入中缀算术表达式:\n");
	gets(input);
	printf("转换后的后缀算术表达式为;\n");
	calculate(input);
	printf("\n\n");
	return 0;
}

三十、使用队列模拟cpu的时间片轮转调度算法

#include<stdio.h>
#include<stdlib.h>
#define MAX 10   //最大进程数
int Time;   //时间片
int process_amount;  //进程数量
int current_number = 0;   //当前执行的“号码牌”
int index = 0;       //就绪队列要发的“号码牌”,初始值为0
struct PCB
{
	char name[10];   //进程名字
	int arrival_time;   //到达时间
	int service_time;   //服务时间
	int completion_time;   //完成时刻
	int sign_completion;  //标志是否完成调用,0表示没完成,1表示完成
	int remaining_time;  //剩余服务时间
	int number;          //进程在就绪队列里的“号码牌”
}process[MAX];

void input()     //初始化进程的信息
{
	int i;
	printf("请输入时间片:\n");
	scanf("%d",&Time);
	printf("请输入进程名称、到达时间、服务时间:\n");
	for(i = 0; i < process_amount; i ++)
	{
		printf("%d号进程:\n",i+1);
		scanf("%s%d%d",process[i].name,&process[i].arrival_time,&process[i].service_time);
		printf("\n");
		process[i].remaining_time = process[i].service_time;
		process[i].sign_completion = 0;
		process[i].number = 0;       //“号码牌”初始为0
	}
}

void BubbleSort()    //冒泡排序算法对进程抵达时间先后排序
{
	int i,j,n = process_amount;
    for(i = 0; i < n - 1; i++)
    for(j = 0; j < n - 1 - i; j++)
	{
		if(process[j].arrival_time > process[j+1].arrival_time)
		{
			process[n] = process[j+1];
			process[j+1] = process[j];
			process[j] = process[n];

		}
	}
}

void RunProcess()     //时间片轮转调用过程
{
	int time = process[0].arrival_time;      //给当前时间赋初值
	int sum = 0;					//记录完成的进程数
	int i,j;
    while(sum < process_amount)
    {
	for(i = 0;  i < process_amount; i++)
		if(current_number == process[i].number && process[i].sign_completion == 0)
		{
		 	if(process[i].remaining_time <= Time)    //剩余服务时间少于等于一个时间片
		 	{
		 	time = time + process[i].remaining_time;
		 	process[i].sign_completion = 1;
		 	process[i].completion_time = time;
		 	process[i].remaining_time = 0;
			printf("%s ",process[i].name);
			sum++;
			current_number++;
			for(j = i + 1; j < process_amount; j++)     //检测后面有没有新进程到达
				if(process[j].arrival_time <= time && process[j].number == 0)
				{
					index++;
					process[j].number = index;
				}
		 	}

		 	else if(process[i].remaining_time > Time)//剩余服务时间大于一个时间片
		 	{
		 		time = time + Time;
				process[i].remaining_time -= Time;
				printf("%s ",process[i].name);
				current_number++;
				for(j = i + 1; j < process_amount; j++)    //检测后面有没有新进程到达
				if(process[j].arrival_time <= time && process[j].number == 0)
				{
					index++;
					process[j].number = index;
				}
				index++;
				process[i].number = index;
			}
		}
	if(index < current_number && sum < process_amount)   // 还有没执行的进程,且没进入就绪队列
	{
	for(i = 0; i <= process_amount; i++)
		if(process[i].sign_completion == 0)
		{
			time = process[i].arrival_time;
			index++;
			process[i].number = index;
			break;
		}
	}
}
}

void output()   //打印信息
{
	int i;
	printf("程序名 到达时间 服务时间 完成时间 周转时间  带权周转时间\n");
	for(i = 0; i < process_amount; i++)
	{
		float weight_time = (float)(process[i].completion_time - process[i].arrival_time)/process[i].service_time;
		printf("  %s\t  %d\t   %d\t    %d\t     %d\t\t%.2f\n",process[i].name,process[i].arrival_time,process[i].service_time,
			process[i].completion_time,process[i].completion_time-process[i].arrival_time,weight_time);
	}
}

int main()
{
	int f;
	printf("模拟时间片轮转法实现进程调度\n");
	printf("请输入总进程数:\n");
	scanf("%d",&process_amount);
	input();
	BubbleSort();
	printf("进程运行顺序:\n");
	RunProcess();
	printf("\n");
	output();
	printf("\n");
	return 0;
}

单词本

#include<stdio.h>
#include<string.h>
#define MaxStrSize 256
/* 根据用户需要自己定义大小 */
typedef struct
{
    char ch[MaxStrSize];
    /* ch是一个可容纳256个字符的字符数组 */
    int length;
} SString;
/* 定义顺序串类型 */
int PartPosition (SString s1,SString s2,int k)
{
    int i,j;
    i=k-1;
    /* 扫描s1的下标,因为c中数组下标是从0开始,串中序号相差1 */
    j=0;
    /* 扫描s2的开始下标 */
     while(i<s1.length && j<s2.length)
    {
        if(s1.ch[i]==s2.ch[j])
        {
            i++;j++;
        /* 继续使下标移向下一个字符位置 */
        }
        else
        {
            i=i-j+1; j=0;
        }
    }
    if (j>=s2.length)
        return i-s2.length;
    else
        return -1;
    /* 表示s1中不存在s2,返回-1 */
    /* 表示s1中存在s2,返回其起始位置 */
    }
    /* 函数结束 */ /*件一个文本文件,在里面输入想要的文本*/
    void CreatTextFile()
    {
        SString S;
        char fname[10],yn;
        FILE *fp;
        printf("输入要建立的文件名:");
        scanf("%s",fname);
        fp=fopen(fname,"w");
        yn='n';/* 输入结束标志初值 */
        while(yn=='n'||yn=='N')
        {
            printf("请输入一行文本:");
            gets(S.ch);
            gets(S.ch);
            S.length=strlen(S.ch);
            fwrite(&S,S.length,1,fp);
            fprintf(fp,"%c",10);/* 是输入换行 */
            printf("结束输入吗?y or n :");
            yn=getchar();
        }
        fclose(fp);/* 关闭文件 */
        printf("建立文件结束!\n");
    } /*输入2进行计算出现次数,输入3可以确定文本出现的位置,以此实现检索单词的出现在文本文件中的行号,次数以及位置*/
    void SubStrCount()
    {
        FILE *fp;
        SString S,T;/* 定义两个串变量 */
        char fname[10];
        int i=0,j,k;
        printf("输入文本文件名:");
        scanf("%s",fname);
        fp=fopen(fname,"r");
        printf("输入要统计计数的单词:");
        scanf("%s",T.ch);
        T.length=strlen(T.ch);
        while(!feof(fp))
        {   /* 扫描整个文本文件 */
            /*  fread(&S.ch,1,sizeof(S),fp);//读入一行文本 */
            memset(S.ch,'\0',256);
        fgets(S.ch,100,fp);
        S.length=strlen(S.ch);
        k=0; /* 初始化开始检索位置 */
        while(k<S.length-1) /* 检索整个主串S */
        {
            j=PartPosition(S,T,k);/* 调用串匹配函数 */
                if(j<0 ) break;
        else
        {
                i++;/* 单词计数器加1 */
        k=j+T.length;/* 继续下一字串的检索 */
        }
        }
        }
        printf("\n单词%s在文本文件%s中共出现%d次\n",T.ch,fname,i);
        }/* 统计单词出现的个数 */
        void SubStrInd()
        {
            FILE *fp;
            SString S,T; /* 定义两个串变量 */
            char fname[10];
            int i,j,k,l,m;
            int wz[20]; /* 存放一行中字串匹配的多个位置 */
            printf("输入文本文件名:");
            scanf("%s",fname);
            fp=fopen(fname,"r");
            printf("输入要检索的单词:");
            scanf("%s",T.ch);
            T.length=strlen(T.ch);
            l=0; /* 行计数器置0 */
            while(!feof(fp))
            { /* 扫描整个文本文件 */
                /* fread(&S,sizeof(S),1,fp);
                //读入一行文本 */
                memset(S.ch,'\0',256);
                fgets(S.ch,256,fp);
                S.length=strlen(S.ch);
                l++; /* 行计数器自增1 */
                k=0;/* 初始化开始检索位置 */
                i=0; /* 初始化单词计数器 */
                while(k<S.length-1) /* 检索整个主串S */
                {
                    j=PartPosition(S,T,k); /* 调用串匹配函数 */
                    if(j<0) break;
                else {
                        i++;/* 单词计数器加1 */
                wz[i]=j;/* 记录匹配单词位置 */
                k=j+T.length;/* 继续下一字串检索 */
                }
                }
                if(i>0)
                {
                        printf("行号:%d,次数:%d,位置分别为:",l,i);
                for(m=1;m<=i;m++) printf("%4d",wz[m]+1); printf("\n");
                }
            }
        }
            void CreatTextFile(),SubStrCount(),SubStrInd();
            int xz;
            int print()
        {
                 printf("===============================================\n");
                 printf("||      文本文件的检索、字串的统计及定位              ||\n");
                 printf("||===========================================   ||\n");
                 printf("||           1.     建立文本文件             ||\n");
                 printf("||           2.     单词字串的计数           ||\n");
                 printf("||           3.     单词字串的定位           ||\n");
                 printf("||           4.     退出整个程序             ||\n");
                 printf("===============================================\n");
                 printf("                请选择(1--4)\n                   ");
                scanf("%d",&xz);
                switch(xz) {
                    case 1 : CreatTextFile();break;
                    case 2 : SubStrCount();break;
                    case 3 : SubStrInd();break;
                    case 4 : return 0;
                    default:printf("选择错误,重新选 \n");
                    }
                return 0;
        }
             /*用此函数来退出文本文件的单词检索*/
                void end()
                {
                    printf("谢谢使用文本文件的单词检索!\n");
                }
                /*主函数,利用无限循环可以进行连续的操作*/
                int main()
                {
                        while(1)
                    {
                        CreatTextFile(),SubStrCount(),SubStrInd();

                    }print();
                    return 0;
                }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值