Ханойские башни и автоматы
Download 201.2 Kb. Pdf ko'rish
|
hanoy-1
глубокой предыстории — в отличие от классических автоматов, переходы из состояния с
номером 2 зависят также и от ранее запомненного в стеке номера следующего состояния. 5 0 1 3 4 x1 z0 иначе push(3); z1 1 push(4); z2 1 push(2); z3 stack[top].y == 3 pop stack[top].y == 4 pop stack[top].y == 2 pop 1: стек пуст 1 2 Рис. 4. Граф переходов, моделирующий работу рекурсивной функции 7. Граф переходов на рис. 4 может быть упрощен за счет исключения неустойчивых вершин (кроме вершины с номером 0). Такой граф переходов приведен на рис. 5. x1 z0 0 1 1: стек пуст иначе push(3); z1 stack[top].y == 3 pop; push(4); z2 stack[top].y == 4 pop; push(2); z3 stack[top].y == 2 pop 1 2 Рис. 5. Упрощенный граф переходов 8. Строится автоматная программа, содержащая функции для работы со стеком и цикл do-while, телом которого является оператор switch, формально и изоморфно построенный по графу переходов [9]. Программа, построенная по графу переходов (рис. 4) и содержащая функции для работы со стеком, приведена на листинге 3. В этой программе операторы, реализующие дуги, исходящие из вершины с номером 2 (за исключением дуги 2–0), закомментированы и заменены одним оператором pop( &y, &i, &j, &k ). Такое упрощение программы, однако, приводит к тому, что по указанному оператору невозможно определить, в какое состояние будет выполнен переход. ЛИСТИНГ 3. Автоматная программа, моделирующая рекурсию #include // Элемент стека. typedef struct { int y, i, j, k ; } stack_t ; stack_t stack[200] ; // Стек. int top = -1 ; // Индекс верхнего элемента в стеке. 6 push( int y, int i, int j, int k ) { top++ ; stack[top].y = y ; stack[top].i = i ; stack[top].j = j ; stack[top].k = k ; printf( "push {%d,%d,%d,%d}: ", y, i, j, k ) ; show_stack() ; } pop( int *y, int *i, int *j, int *k ) { printf( "pop {%d,%d,%d,%d}: ", stack[top].y, stack[top].i, stack[top].j, stack[top].k ) ; if( y ) *y = stack[top].y ; *i = stack[top].i ; *j = stack[top].j ; *k = stack[top].k ; top-- ; show_stack() ; } int stack_empty() { return top < 0 ; } // Вывод содержимого стека для протоколирования. void show_stack() { int i ; for( i = top ; i >= 0 ; i-- ) printf( "{%d,%d,%d,%d} ", stack[i].y, stack[i].i, stack[i].j, stack[i].k ) ; printf( "\n" ) ; } void hanoy( int i, int j, int k ) { int y = 0 ; do switch( y ) { case 0: y = 1 ; break ; case 1: if( k == 1 ) { move( i, j ) ; y = 2 ; } else { push( 3, i, j, k ) ; j = 6-i-j ; k-- ; } break ; case 2: if( stack_empty() ) y = 0 ; else pop( &y, &i, &j, &k ) ; /* Эта операция pop() заменяет закомментированные операторы, но при этом теряется однозначное соответствие программы графу переходов. */ /* if( stack[top].y == 4 ) { pop( NULL, &i, &j, &k ) ; y = 4 ; } else if( stack[top].y == 3 ) { pop( NULL, &i, &j, &k ) ; y = 3 ; } else if( stack[top].y == 2 ) { pop( NULL, &i, &j, &k ) ; } */ break ; 7 case 3: push( 4, i, j, k ) ; k = 1 ; y = 1 ; break ; case 4: push( 2, i, j, k ) ; i = 6-i-j ; k-- ; y = 1 ; break ; } while( y != 0 ) ; } void move( i, j ) { printf( "%d -> %d\n", i, j ) ; } int main() { int input = 3 ; printf( "\nХаной с %d дисками:\n", input ) ; hanoy( 1, 3, input ) ; return 0 ; } Возможны и другие варианты реализации функций pop() и push(), например, с передачей в качестве параметра указателя на переменную типа stack_t. Если функцию hanoy() в этой программе реализовать не по графу переходов (рис. 4), а по графу, полученному после его упрощения (рис. 5), то она сокращается (листинг 4). ЛИСТИНГ 4. Автоматная программа с минимизированным числом состояний, моделирующая рекурсию void hanoy( int i, int j, int k ) { int y = 0 ; do switch( y ) { case 0: y = 1 ; break ; case 1: if( k == 1 ) { move( i, j ) ; y = 2 ; } else { push( 3, i, j, k ) ; j = 6 - i - j ; k-- ; } break ; case 2: if( stack_empty() ) y = 0 ; else if( stack[top].y == 4 ) { pop( NULL, &i, &j, &k ) ; push( 2, i, j, k ) ; i = 6 - i - j ; k-- ; y = 1 ; } else if( stack[top].y == 3 ) { pop( NULL, &i, &j, &k ) ; push( 4, i, j, k ) ; k = 1 ; y = 1 ; } else 8 if( stack[top].y == 2 ) { pop( NULL, &i, &j, &k ) ; } break ; } while( y != 0 ) ; } Отметим, что при такой реализации, в отличие от программы, приведенной в листинге 3, не удается выполнить ее дальнейшее упрощение за счет замены трех условий переходов одной функцией pop(). Выше был расмотрен метод, обеспечивающий построение автоматов Мили. Аналогичный метод может быть предложен и для построения автоматов Мура. Download 201.2 Kb. Do'stlaringiz bilan baham: |
Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling
ma'muriyatiga murojaat qiling