数据结构和算法分析(10)表栈和队列的实际应用

Posted MenAngel

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构和算法分析(10)表栈和队列的实际应用相关的知识,希望对你有一定的参考价值。

    本节继续介绍表、栈、队列在编程实践中的应用。

 

    (1)行编辑程序:(允许用户输入出差错,并在发现错误时可以及时更正。)

    功能:接受用户从终端输入的字符型的数据,并存入用户的数据区。由于不能保证不出差错,因此“每接受一个字符即存入用户数据区”的做法不是最恰当的;较好的做法是,设立一个输入的缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。

    算法原理当用户发现刚刚键入的一个字符是错的时,可补进一个退格符“#”,以表示前一个字符无效;如果发现当前键入的行内差错较多或者难以补救,则可以键入一个退行符“@”,以表示当前行中的字符均无效。

 1 #include <stdio.h>
 2 
 3 #define STACK_SIZE 100  //自定义能够临时存储用户输入的字符数
 4 #define STACKINCREMENT 10
 5 #define OVERFLOW -2
 6 typedef char ElemType;
 7 struct StackNode{
 8     ElemType *base;
 9     ElemType *top;
10     int stacksize;
11 };
12 typedef struct StackNode *TempStack;
13 void InitStack(TempStack S,int stackSize);
14 void Push(TempStack S,ElemType e);
15 void Pop(TempStack S,ElemType *e);
16 void DestoryStack(TempStack S);
17 void LineEdit(TempStack S);
18 void ClearStack(TempStack S);
19 
20 void InitStack(TempStack S,int stackSize) {
21     S->base = (ElemType *)malloc(stackSize*sizeof(ElemType));
22     if(!S->base) { 
23         printf("内存不足!\\n");
24         exit(OVERFLOW);
25     }
26     S->top = S->base;
27     S->stacksize = stackSize;
28 }
29 void Push(TempStack S,ElemType e) {
30     //这段话能够使程序有很好的扩容性 
31     if((S->top-S->base)>=S->stacksize) {
32         S->base = (ElemType*)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(ElemType));
33         if(!S->base) {
34             exit(OVERFLOW);
35         }
36         S->top = S->base + S->stacksize;
37         S->stacksize += STACKINCREMENT;
38     }
39     *S->top++ = e;
40 }
41 void Pop(TempStack S,ElemType *e) {
42     if(S->top == S->base) 
43       return;
44     *e = *--S->top;
45 }
46 void ClearStack(TempStack S) {
47     S->top = S->base;
48 }
49 void DestoryStack(TempStack S) {
50     S->top = S->base;
51     free(S->base);
52     S->top = NULL;
53     S->base = NULL;
54 }
55 void LineEdit(TempStack S) {
56     ElemType *p,ch,c;
57     InitStack(S, STACK_SIZE);
58     ch = getchar();
59     while(ch != EOF) {
60         //进行字符入栈操作 
61         while(ch!=EOF&&ch!=\'\\n\') {
62             switch(ch) {
63                 case \'#\':Pop(S,&c);break;
64                 case \'@\':ClearStack(S);break;
65                 default:Push(S,ch);break;
66             }
67             ch = getchar();
68         }
69         Push(S,ch);//最后的回车也要进入临时区 
70         //遍历栈中的字符 
71         p = S->base;
72         while(p!=S->top) {
73             printf("%c",*p);
74             ++p;
75         }
76         ClearStack(S);
77         if(ch!=EOF) ch = getchar();
78     }
79 }
80 int main(){
81     TempStack sq;
82     LineEdit(sq);
83     DestoryStack(sq);
84     return 0;
85 }

    一个可调整的地方:

    在接受终端输入时,每输入每一行字符(按回车)行编辑程序就自动执行一次,并返回临时栈中所有字符组成的字符串,并再次调用自身,当一行字符为空时程序运行结束。这个程序的缺点在于输出与处理没有分开。

 

    (2)自调整链表:

    自调整表如同一个规则的表,但是所有的插入都在表头进行。当一个元素被Find访问时,它就被移到表头而不改变其余项的相对位置。

    1)数组实现:

 1 /*---------------数组法实现自调整链表---------------*/ 
 2 #include <stdio.h>
 3 #define LIST_SIZE 30 //数组大小 
 4 typedef char ElemeType;
 5 
 6 struct ListNode{
 7   ElemeType *Array;
 8   int num;
 9   int Capicity;
10 };
11 typedef struct ListNode *List; 
12 List CreateList(int size){
13   List list=malloc(sizeof(struct ListNode));
14   list->Array=malloc(size*sizeof(ElemeType));
15   list->num=0;
16   list->Capicity=size;
17   return list;
18 }
19 void InitList(List list){
20     int i;
21     for(i=0;i<26;i++){
22         list->Array[list->num]=(ElemeType)(\'A\'+list->num);
23         list->num++;
24     }
25 }
26 void printList(List list){
27     int i;
28     for(i=0;i<list->num;i++){ 
29       putchar(list->Array[i]);
30       putchar(\' \'); 
31     } 
32 }
33 void find(ElemeType ch,List list){
34     int i;
35     for(i=0;i<list->num;i++){
36         if(ch==list->Array[i]){
37           int j;
38           for(j=i;j>0;j--)
39               list->Array[j]=list->Array[j-1];
40           list->Array[0]=ch;      
41           return;    
42         }
43     }
44     printf("链表里没有这个元素%c",ch); 
45 }
46 int main(){
47   List list=CreateList(LIST_SIZE);
48   InitList(list); 
49   printList(list);
50   ElemeType temp[20]={
51   \'B\',\'Z\',\'B\',\'C\',\'W\',
52   \'Z\',\'R\',\'E\',\'B\',\'V\',
53   \'E\',\'W\',\'E\',\'T\',\'S\',
54   \'B\',\'C\',\'K\',\'B\',\'C\'
55   };//B出现5次,E、C出现3次,Z出现2次,W出现2次,R、K、T、V、S各一次
56   int i;
57   for(i=0;i<20;i++){
58       find(temp[i],list);
59   }
60   printf("\\n自调整后的链表是:\\n");
61   printList(list);
62   printf("\\n");
63   return 0;
64 }

    2)链表实现:

 1 /*---------------链表法实现自调整链表---------------*/ 
 2 #include <stdio.h>
 3 typedef char ElemeType;
 4 
 5 struct ElemeNode{
 6     ElemeType element;
 7     struct ElemeNode *next;
 8 };
 9 typedef struct ElemeNode *PtrToNode;
10 typedef PtrToNode List;
11 List createList(){
12     List list=malloc(sizeof(struct ElemeNode));
13     list->next=NULL;
14     return list;
15 }
16 void InsertIntoList(ElemeType temp,List list){
17     PtrToNode ptr=malloc(sizeof(struct ElemeNode));
18     ptr->element=temp;
19     ptr->next=list->next;
20     list->next=ptr;
21 }
22  
23 InitList(List list){
24     int i;
25     for(i=25;i>=0;i--){
26         ElemeType temp=(ElemeType)((int)\'A\'+i);
27         InsertIntoList(temp,list);    
28     }
29 }
30 void printList(List list){
31     PtrToNode ptr=list->next;
32     while(ptr){
33         putchar(ptr->element);
34         putwchar(\' \');
35         ptr=ptr->next;
36     }
37 }
38 int DeleteFromList(ElemeType element,List list){
39     PtrToNode ptr=list;
40     while(ptr->next->element!=element){
41         ptr=ptr->next;
42     }
43     if(ptr->next==NULL){
44         return 0;//没有此元素 
45     }else{
46         ptr->next=ptr->next->next;
47         return 1;
48     } 
49 }
50 void find(ElemeType    element,List list){
51     if(DeleteFromList(element,list))
52       InsertIntoList(element,list);
53     else
54       printf("没有此元素!\\n");
55 }
56 int main(){
57   List list=createList();
58   InitList(list);
59   printList(list);
60   ElemeType temp[20]={
61       \'B\',\'Z\',\'B\',\'C\',\'W\',
62       \'Z\',\'R\',\'E\',\'B\',\'V\',
63       \'E\',\'W\',\'E\',\'T\',\'S\',
64       \'B\',\'C\',\'K\',\'B\',\'C\'
65   };//B出现5次,E、C出现3次,Z出现2次,W出现2次,R、K、T、V、S各一次
66     int i;
67   for(i=0;i<20;i++){
68       find(temp[i],list);
69   }
70   printf("\\n自调整后的链表是:\\n");
71   printList(list);
72   printf("\\n");
73   return 0;    
74 }

 

    (3)用一个数组实现多个栈:(除非数组中的每个单元都被使用否则不能有溢出声明)

    算法原理:对与不支持指针的语言(例如java)采用游标法实现表:(与这个例子作对比:http://www.cnblogs.com/MenAngel/p/5539085.html)

  1 /*---------------游标模式下栈的实现---------------*/
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #define SpaceSize 60
  5 
  6 typedef int PtrToNode;
  7 typedef PtrToNode Stack;
  8 typedef PtrToNode Position;
  9 
 10 struct Node{
 11     int Element; 
 12     int flag;//记录元素出现的次数 
 13     Position Next;//Next指针指向的不是具体的结点的首地址,而是结点的下标 
 14 };
 15 //编译时预先分配的结点数组 
 16 struct Node CursorSpace[SpaceSize];
 17 //CursorSpace[0]是表头指针 
 18 static void InitialCursor(void){
 19     int i;
 20     for(i=0;i<SpaceSize;i++){
 21         CursorSpace[i].Next=i+1;
 22     }
 23     CursorSpace[i].Next=0;
 24 } 
 25 
 26 static Position CursorAlloc(void){
 27     Position p;
 28     p=CursorSpace[0].Next;
 29     CursorSpace[0].Next=CursorSpace[p].Next;
 30     CursorSpace[p].Next=0;
 31     return p;//当p的值为0时说明没有空间可用了    
 32 } 
 33 
 34 static void CursorFree(Position p){
 35     CursorSpace[p].Next=CursorSpace[0].Next;
 36     CursorSpace[0].Next=p;
 37 }
 38 void InitStack(Stack *S){
 39     PtrToNode p=CursorAlloc();
 40     //新建的结点需要指向头结点 
 41     CursorSpace[p].Next=0;
 42     *S=p;
 43 }
 44 
 45 int IsLast(Position p,Stack S){
 46     return CursorSpace[p].Next==0;
 47 }
 48 void InsertIntoStack(int x,Stack S){
 49     Position TmpCell;
 50     TmpCell=CursorAlloc();
 51     if(TmpCell==0){
 52         printf("空间已经使用完,溢出!\\n");
 53         //exit(0);
 54         return; 
 55     }
 56     CursorSpace[TmpCell].Element=x;
 57     CursorSpace[TmpCell].flag=1; 
 58     CursorSpace[TmpCell].Next=CursorSpace[S].Next;
 59     CursorSpace[S].Next=TmpCell;
 60 }
 61 void printStack(Stack stack){
 62     Position p=stack;
 63     Position temp;
 64     int i;
 65     int w=0; 
 66     while((temp=CursorSpace[p].Next)!=0){
 67         //printf("%d",CursorSpace[temp].flag);
 68          for(i=0;i<CursorSpace[temp].flag;i++){
 69              printf("%3d",CursorSpace[temp].Element);
 70              w++;
 71              if(w%30==0){
 72                  printf("\\n");
 73              }
 74          }
 75          p=CursorSpace[p].Next;
 76     }
 77 }
 78 int main(){
 79     InitialCursor();
 80     Stack stack_a;InitStack(&stack_a);
 81     Stack stack_b;InitStack(&stack_b);
 82     Stack stack_c;InitStack(&stack_c);
 83     Stack stack_d;InitStack(&stack_d);
 84     int i;
 85     int rand_num;
 86     //程序准备的是60个,这里需要4+57=61个空间,一次最后一次操作将会溢出 
 87     for(i=0;i<=56;i++){
 88         rand_num=rand()%4+1;
 89         switch(rand_num){
 90           case 1:InsertIntoStack(i,stack_a);break;
 91           case 2:InsertIntoStack(i,stack_b);break;
 92           case 3:InsertIntoStack(i,stack_c);break;
 93           case 4:InsertIntoStack(i,stack_d);break;
 94           default:printf("出现错误\\n");             
 95         }
 96     }
 97     printf("栈a中的元素有:\\n");
 98     printStack(stack_a); 
 99     printf("\\n栈b中的元素有:\\n");    
100     printStack(stack_b); 
101     printf("\\n栈c中的元素有:\\n");
102     printStack(stack_c); 
103     printf("\\n栈d中的元素有:\\n");
104     printStack(stack_d); 
105     printf("\\n");
106     return 0;
107 }

 

    (4)渡轮模拟问题:(队列的实际应用)

    有一个渡口,每条渡船能一次性装载10辆汽车过河,车辆分为客车和货车两类。上渡轮有如下规定:

    1.同类车辆先到先上船,客车先于货车上船;

    2.每上3辆客车才允许上一辆货车,但若等待的客车不足4辆则用货车填补,反过来,若没有货车等待则用客车填补。

    3.装满10辆后则自动开船,当等待时间较长时车辆不足10辆也应认为控制发船。

    1)c语言版本:

  1 /*---------------队列模拟渡轮问题---------------*/
  2 #include <stdio.h> 
  3 #include <stdlib.h>
  4 #include <time.h>
  5 #include <string.h>
  6 #define YES 1
  7 #define NO  0;
  8 //采用链表法实现队列
  9 struct CarNode{
 10     char name[5];//存车辆的名称
 11以上是关于数据结构和算法分析(10)表栈和队列的实际应用的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法分析表栈和队列

数据结构和算法分析 表栈和队列

数据结构与算法分析表栈和队列

表栈和队列

数据结构与算法第三章:表栈和队列

数据结构和算法 数据结构基础线性表栈和队列数组和字符串