探讨两种方法解决大小、数字字符排序问题

来源:互联网 发布:苹果刷机后数据恢复 编辑:程序博客网 时间:2024/06/06 23:57

一 问题描述

一个字符数组,里面的字符可能是a-z、A-Z、0-9.现在要求对数组进行排序,要求所有小写字符放在最前面,所有大写字符放在中间,所有数字放在最后,而且各部分内部分别有序。

二 解题思路

方法一 利用快排


如图所示,为了能够实现排序,首先将原始字符串进行一次二次划分,将所有小写字符移动到字符串的最开始,然后对此段子序列进行快速排序,然后依据同样的方法对大写字符和数字字符进行排序。

方法二:


如图所示,首先定义哈希表,然后根据原始字符串对哈希表进行初始化,那么在哈希表中,小写字符必然在大写字符前,大写字符必然在数字字符前,最后将哈希表里的内容拷贝回原始字符串中。

三 运行测试

方法一测试结果:


方法二测试结果


四 代码

方法一代码:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <ctype.h>#define SIZE 100int partition(char *array, int low, int high) {int i, j;char tmp;i = low;j = high;tmp = array[low];while(i < j) {while(i < j && array[j] > tmp) j--;if(i < j) array[i++] = array[j];while(i < j && array[i] < tmp) i++;if(i < j) array[j--] = array[i];}array[i] = tmp;return i;}void self_qsort(char *array, int low, int high) {if(low < high) {int mid = partition(array, low, high);self_qsort(array, low, mid - 1);self_qsort(array, mid + 1, high);}}void Arrange(char *str, int low, int high) {int lower_end;    // the end pointer to lower char arrayint i, j;/* * to put all the lower char in the front of array*/i = low;j = high;char tmp = str[low];while(i < j) {while(i < j && !islower(str[j])) j--;if(i < j) str[i++] = str[j];while(i < j && islower(str[i])) i++;if(i < j) str[j--] = str[i];}/* * to locate the lower_end*/str[i] = tmp;if(islower(str[i])) lower_end = i;else lower_end = i - 1;/* * to sort the lower char in the array*/self_qsort(str, 0, lower_end);/* * to put the upper char in the front of digital char in the array*/int upper_end;i = lower_end + 1;j = high;tmp = str[i];while(i < j) {while(i < j && !isupper(str[j])) j--;if(i < j) str[i++] = str[j];while(i < j && isupper(str[i])) i++;if(i < j) str[j--] = str[i];}str[i] = tmp;/* * to locate the upper_end*/if(isupper(str[i])) upper_end = i;else upper_end = i - 1;self_qsort(str, lower_end + 1, upper_end); // to sort the upper charself_qsort(str, upper_end + 1, high);   // to sort the digital char}int main() {        char str[SIZE];printf("input a string(only contains 'a' - 'z', 'A' - 'Z', '0' - '9')");gets(str);int i;for(i = 0;str[i];i++) {if(!islower(str[i]) && !isupper(str[i]) && !isdigit(str[i])) {fprintf(stderr, "input error!\n");exit(EXIT_FAILURE);}}int len = strlen(str);Arrange(str, 0, len - 1);puts(str);return 0;}

方法二代码:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <ctype.h>#define SIZE 100#define HashTableLen 62int HashTable[HashTableLen];  // to define a Hash Table/* * Hash Function: Mapping a char to a interger position*/int Hash(char ch) {int pos;if(islower(ch)) pos = ch - 'a';else if(isupper(ch)) pos = ch - 'A' + 26;else if(isdigit(ch)) pos = ch - '0' + 52;else pos = -1;return pos;}/* * Reverse Hash Function: Mapping a position to a char*/char ReHash(int pos) {if(pos < 26 && pos >= 0) return 'a' + pos;if(pos < 52 && pos >= 26) return 'A' + pos - 26;if(pos < 62 && pos >= 52) return '0' + pos - 52; }/* * to initialize a Hash table*/void InitHash(char *str, int low, int high) {int i;int pos;for(i = low;i <= high;i++) {pos = Hash(str[i]);if(pos == -1) {perror("error position in the hash table!\n");exit(EXIT_FAILURE);}HashTable[pos]++;}}int main() {        char str[SIZE];printf("input a string(only contains 'a' - 'z', 'A' - 'Z', '0' - '9')");gets(str);int i;/* * to check the validity*/for(i = 0;str[i];i++) {if(!islower(str[i]) && !isupper(str[i]) && !isdigit(str[i])) {fprintf(stderr, "input error!\n");exit(EXIT_FAILURE);}}int len = strlen(str);InitHash(str, 0, len - 1);int j = 0;/* * to regenerate the string */for(i = 0; i < HashTableLen;i++) {while(HashTable[i]-- > 0) {str[j++] = ReHash(i);}}puts(str);return 0;}

五 编程体会

   这个问题本质还是排序问题,但是属于特殊排序,第一种方法利用快排,时间效率较高,而方法二要使用额外的空间,不过方法更加巧妙。

0 0
原创粉丝点击