数制转换
在计算机中经常面对不同数制的转换问题,如将一个十进制数N转换为d进制B。数制转换的解决方法很多,其中一个简单的转换算法是重复下述两步。直到N等于零为止。
x = N mod d
N = N div d
其中,N为需要转换的十进制数,d为转换后的进制,x值为转换后各个数位上的数,div为整除运算,mod为求余运算。算法的运行过程为:第一次求出的x值为d进制数的最低位,最后一次求出的x值为d进制数的最高位,所以上述算法是从低位到高位顺序产生d进制的各位,然后逆序输出,因为它按“后进先出”的规律进行的,所以用栈这种结构处理最合适。根据这个特点,利用栈来实现上述数制转换,即将计算过程种一次得到的d进制数码按顺序栈进栈。计算结束后,再返顺序出栈,并按出栈顺序打印输出。这样即可得到给定的十进制数对应的d进制数,由此可以得到数制转换的算法。
实现代码
利用顺序栈实现数制转换(以十进制转换为二进制为例)
1 #include <stdlib.h> 2 #include <stdio.h> 3 #define MAXSIZE 1024 4 5 /*定义顺序栈*/ 6 typedef int elemtype; 7 typedef struct SequenStack 8 { 9 elemtype data[MAXSIZE]; 10 int top; 11 }SequenStack; 12 13 /*判(顺序栈)栈空*/ 14 SequenStack * Init_SequenStack() 15 { 16 SequenStack * S; 17 S = (SequenStack *)malloc(sizeof(SequenStack)); 18 19 if (S == NULL) 20 { 21 return S; 22 } 23 S->top = -1; 24 return S; 25 } 26 27 /* 判空栈(顺序栈)*/ 28 int SequenStack_Empty(SequenStack * S) 29 { 30 if (S->top == -1) 31 { 32 return 1; 33 } 34 else 35 { 36 return 0; 37 } 38 } 39 40 /* 入栈(顺序栈) */ 41 int Push_SequenStack(SequenStack * S, elemtype x) 42 { 43 if (S->top >= MAXSIZE-1) 44 { 45 return 0; 46 } 47 S->top++; 48 S->data[S->top] = x; 49 return 1; 50 } 51 52 /* 出栈(顺序栈) */ 53 int Pop_SequenStack(SequenStack * S, elemtype * x) 54 { 55 if (S->top == -1) 56 { 57 return 0; 58 } 59 else 60 { 61 S->top--; 62 *x = S->data[S->top+1]; 63 return 1; 64 } 65 } 66 67 /* 进制转换算法 */ 68 void SequenStackConversion(int N) 69 { 70 int x; 71 SequenStack * S = Init_SequenStack(); 72 while (N > 0) 73 { 74 Push_SequenStack(S, N % 2); 75 N = N / 2; 76 } 77 while (! SequenStack_Empty(S)) 78 { 79 Pop_SequenStack(S, &x); 80 printf("%d", x); 81 } 82 } 83 84 int main() 85 { 86 int N; 87 printf("Please enter the decimal number you want want to convert:\n"); 88 scanf("%d", &N); 89 printf("The converted binary number is:\n"); 90 SequenStackConversion(N); 91 }
实现结果:
利用链栈栈实现数制转换(以十进制转换为二进制为例)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 /*定义链栈*/ 5 typedef int elemtype; 6 typedef struct LinkedStackNode 7 { 8 elemtype data; 9 struct LinkedStackNode *next; 10 }LinkedStackNode, *LinkedStack; 11 LinkedStack top; 12 13 /*链栈的初始化*/ 14 LinkedStack Init_LinkedStack() 15 { 16 LinkedStack top = (LinkedStackNode *)malloc(sizeof(LinkedStackNode)); 17 18 if(top != NULL) 19 { 20 top->next = NULL; 21 } 22 return top; 23 } 24 25 /*判栈空*/ 26 int LinkedStack_Empty(LinkedStack top) 27 { 28 if (top->next == NULL) 29 { 30 return 1; 31 } 32 else 33 { 34 return 0; 35 } 36 37 } 38 39 /*入栈*/ 40 int Push_LinkedStack(LinkedStack top, elemtype x) 41 { 42 LinkedStackNode *node; 43 node = (LinkedStackNode *)malloc(sizeof(LinkedStackNode)); 44 45 if (node == NULL) 46 { 47 return 0; 48 } 49 else 50 { 51 node->data = x; 52 node->next = top->next; 53 top->next = node; 54 return 1; 55 } 56 57 } 58 59 /*出栈*/ 60 int Pop_LinkedStack(LinkedStack top, elemtype * x) 61 { 62 LinkedStackNode *node; 63 if (top->next == NULL) 64 { 65 return 0; 66 } 67 else 68 { 69 node = top->next; 70 *x = node->data; 71 top->next = node->next; 72 free(node); 73 return 1; 74 } 75 76 } 77 78 /*进制转换*/ 79 void ListStackConversion(int N) 80 { 81 int x; 82 LinkedStack S = Init_LinkedStack(); 83 while (N > 0) 84 { 85 Push_LinkedStack(S, N % 2); 86 N = N / 2; 87 } 88 while (! LinkedStack_Empty(S)) 89 { 90 Pop_LinkedStack(S, &x); 91 printf("%d", x); 92 } 93 94 } 95 96 int main() 97 { 98 int N; 99 printf("Please enter the decimal number you want want to convert:\n"); 100 scanf("%d", &N); 101 printf("The converted binary number is:\n"); 102 ListStackConversion(N); 103 }
实现结果:
把顺序栈和链栈两种功能综合在一起实现数制转换(以十进制转换为十六进制为例)
1 /* 进制转换 */ 2 #include <stdlib.h> 3 #include <stdio.h> 4 #define MAXSIZE 100 /*定义顺序栈的长度*/ 5 6 /*定义顺序栈*/ 7 typedef int elemtype; 8 typedef struct SequenStack 9 { 10 elemtype data[MAXSIZE]; 11 int top; 12 }SequenStack; 13 14 /*定义链栈*/ 15 typedef int elemtype; 16 typedef struct LinkedStackNode 17 { 18 elemtype data; 19 struct LinkedStackNode *next; 20 }LinkedStackNode, *LinkedStack; 21 LinkedStack top; 22 23 /* 顺序栈初始化 */ 24 SequenStack * Init_SequenStack() 25 { 26 SequenStack * S; 27 S = (SequenStack *)malloc(sizeof(SequenStack)); 28 29 if (S == NULL) 30 { 31 return S; 32 } 33 S->top = -1; 34 return S; 35 } 36 37 /*链栈的初始化*/ 38 LinkedStack Init_LinkedStack() 39 { 40 LinkedStack top = (LinkedStackNode *)malloc(sizeof(LinkedStackNode)); 41 42 if(top != NULL) 43 { 44 top->next = NULL; 45 } 46 return top; 47 } 48 49 /*判栈(顺序栈)空*/ 50 int SequenStack_Empty(SequenStack * S) 51 { 52 if (S->top == -1) 53 { 54 return 1; 55 } 56 else 57 { 58 return 0; 59 } 60 } 61 62 /* 判栈(链栈)空 */ 63 int LinkedStack_Empty(LinkedStack top) 64 { 65 if (top->next == NULL) 66 { 67 return 1; 68 } 69 else 70 { 71 return 0; 72 } 73 74 } 75 76 /* 入栈(顺序栈)*/ 77 int Push_SequenStack(SequenStack * S, elemtype x) 78 { 79 if (S->top >= MAXSIZE-1) 80 { 81 return 0; 82 } 83 S->top++; 84 S->data[S->top] = x; 85 return 1; 86 } 87 88 /* 出栈(顺序栈) */ 89 int Pop_SequenStack(SequenStack * S, elemtype * x) 90 { 91 if (S->top == -1) 92 { 93 return 0; 94 } 95 else 96 { 97 S->top--; 98 *x = S->data[S->top+1]; 99 return 1; 100 } 101 } 102 103 /* 入栈(链栈) */ 104 int Push_LinkedStack(LinkedStack top, elemtype x) 105 { 106 LinkedStackNode *node; 107 node = (LinkedStackNode *)malloc(sizeof(LinkedStackNode)); 108 109 if (node == NULL) 110 { 111 return 0; 112 } 113 else 114 { 115 node->data = x; 116 node->next = top->next; 117 top->next = node; 118 return 1; 119 } 120 121 } 122 123 /* 出栈(链栈) */ 124 int Pop_LinkedStack(LinkedStack top, elemtype * x) 125 { 126 LinkedStackNode *node; 127 if (top->next == NULL) 128 { 129 return 0; 130 } 131 else 132 { 133 node = top->next; 134 *x = node->data; 135 top->next = node->next; 136 free(node); 137 return 1; 138 } 139 140 } 141 142 /* 使用顺序方式进行进制转换的函数 */ 143 void SequenStackConversion(int N) 144 { 145 int x; 146 SequenStack * S = Init_SequenStack(); 147 while (N > 0) 148 { 149 Push_SequenStack(S, N % 16); 150 N = N / 16; 151 } 152 while (! SequenStack_Empty(S)) 153 { 154 Pop_SequenStack(S, &x); 155 switch (x) 156 { 157 case 10: 158 printf("A"); 159 break; 160 case 11: 161 printf("B"); 162 break; 163 case 12: 164 printf("C"); 165 break; 166 case 13: 167 printf("D"); 168 break; 169 case 14: 170 printf("E"); 171 break; 172 case 15: 173 printf("F"); 174 break; 175 default: 176 printf("%d", x); 177 break; 178 } 179 } 180 } 181 182 /* 使用链栈方式进行进制转换的函数 */ 183 void ListStackConversion(int N) 184 { 185 int x; 186 LinkedStack S = Init_LinkedStack(); 187 while (N > 0) 188 { 189 Push_LinkedStack(S, N % 16); 190 N = N / 16; 191 } 192 while (! LinkedStack_Empty(S)) 193 { 194 Pop_LinkedStack(S, &x); 195 switch (x) 196 { 197 case 10: 198 printf("A"); 199 break; 200 case 11: 201 printf("B"); 202 break; 203 case 12: 204 printf("C"); 205 break; 206 case 13: 207 printf("D"); 208 break; 209 case 14: 210 printf("E"); 211 break; 212 case 15: 213 printf("F"); 214 break; 215 default: 216 printf("%d", x); 217 break; 218 } 219 220 } 221 222 } 223 224 void function() 225 { 226 printf("-------------------------------------------\n"); 227 } 228 229 /* 主函数调用进制转换函数 */ 230 int main() 231 { 232 int N, x; 233 printf("Please enter the decimal number you want want to convert:\n"); 234 scanf("%d", &N); 235 function(); 236 printf("Choose using sequential stack or list stack\n"); 237 printf("1:Sequential stack 2:list stack:\n"); 238 function(); 239 scanf("%d", &x); 240 printf("The converted binary number is:\n"); 241 switch (x) 242 { 243 case 1: 244 SequenStackConversion(N); 245 break; 246 case 2: 247 ListStackConversion(N); 248 break; 249 default: 250 printf("error"); 251 break; 252 } 253 254 return 0; 255 }
值得注意的是,当十进制转换为十六进制的时候,需要考虑输出现实大于9的十六进制位数,这里我们考虑可以使用switch开关实现。
实现结果:
数制转换的算法实现是利用栈的“LIFO”(后进先出)特性的简单例子。当然,也可以用数组实现,那样空间复杂度会降低,但是用栈实现时,其逻辑过程更清楚。