PAT DS 4-09. 笛卡尔树

简单的问题不必复杂话,应该直接码出来再说。

这题在printDirTree时打算用栈来保存每层目录,因为想着直接比较可能会比较费时。结果绕了一圈,发现还是直接比较简单明了。

这题我的思路是,先qsort所有路径,再输出目录树。

qsort的比较函数要仔细思考,避免遗漏边界(比如ab\cd\ 和ab\cd 的比较,ab\cd 和ab\c 的比较)。

输出目录树主要是前后两条路径的比较,要记录目录层数和相同路径的截止点。


<span style="font-size:18px;">#include <stdio.h>
#include <assert.h>
#include <stdbool.h>

#define NAME_SIZE 261
int n;

char input[10000][NAME_SIZE];

int nameCmp(const void *v1, const void *v2);
void printDirTree();

int main(void)
{
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	int i=0;
	for(; i<n; ++i)
		scanf("%s", *(input+i));
#ifdef DEBUG
	printf("\nOriginal data:\n");
	for(i=0; i<n; ++i)
		printf("%s\n", *(input+i));
#endif

	qsort(input, n, NAME_SIZE, nameCmp);
#ifdef DEBUG
	printf("\nqsorted data:\n");
	for(i=0; i<n; ++i)
		printf("%s\n", *(input+i));
#endif

	printDirTree();

	return 0;
}

int nameCmp(const void *v1, const void *v2)
{
#ifdef DEBUG
	//printf("in function nameCmp.\n");
#endif
	char *s1 = (char*)v1, *s2 = (char*)v2;
	int i=0;
	for(; s1[i]!=0 && s2[i]!=0; ++i){
		if(s1[i] == s2[i])
			continue;
		else if(s1[i] == '\\')
			return -1;
		else if(s2[i] == '\\')
			return 1;
		else
			break;
	}
	assert(s1[i] != s2[i]);
	if(s1[i] == 0 && s1[i-1] == '\\')
		return -1;
	if(s2[i] == 0 && s2[i-1] == '\\')
		return 1;
	int j=i;
	if(s1[j] < s2[j]){
		for(j=i; s1[j]!=0; ++j)
			if(s1[j] == '\\')
				return -1;
		for(j=i; s2[j]!=0; ++j)		// only if there's no directory in s1
			if(s2[j] == '\\')		// but is at least one directory in s2
				return 1;			// will return 1
		return -1;
	}
	if(s1[j] > s2[j]){
		for(j=i; s2[j]!=0; ++j)
			if(s2[j] == '\\')
				return 1;
		for(j=i; s1[j]!=0; ++j)
			if(s1[j] == '\\')
				return -1;
		return 1;
	}
}

void printOne(char *file, int depth, int dMark);

void printDirTree()
{
#ifdef DEBUG
	printf("\nOutput:\n");
#endif
	printf("root\n");

	printOne(input[0], 1, 0);
	int i = 1;
	for(; i<n; ++i){		// compare to the previous one and print
		int depth=1, dMark=-1;
		int j=0;
		for(; input[i][j]!=0 && input[i-1][j]!=0; ++j){
			if(input[i][j] == '\\'){
				++depth;
				dMark = j;
			}
			if(input[i][j] != input[i-1][j])
				break;
		}
#ifdef DEBUG
	//	printf("%s : %s\n", input[i-1], input[i]);
#endif
		assert(input[i][j] != 0 || (input[i][j]==0 && input[i-1][j]=='\\'));
		printOne(input[i], depth, dMark+1);
	}
}

void printOne(char *file, int depth, int dMark)
{
	assert(file[0] != '\\' && depth > 0 && dMark >= 0);
	char tmp[261];
	int i=dMark, k=0;
	for(; file[i] != 0; ++i, ++k){
		if(file[i] == '\\'){
			tmp[k] = 0;
			for(k=0; k<depth; ++k)
				printf("  ");
			printf("%s\n", tmp);

			++depth;
			k=-1;
			continue;
		}
		tmp[k] = file[i];
	}
	if(k > 0){
		tmp[k] = 0;
		for(k=0; k<depth; ++k)
			printf("  ");
		printf("%s\n", tmp);
	}
}</span>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值