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

一 问题描述

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

二 解题思路

方法一 利用快排


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

方法二:


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

三 运行测试

方法一测试结果:


方法二测试结果


四 代码

方法一代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#define SIZE 100
int 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 array
		int 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 char
		self_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 62
int 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值