1. 程式人生 > >資料結構與演算法題目集7-30——目錄樹

資料結構與演算法題目集7-30——目錄樹

我的資料結構與演算法題目集程式碼倉:https://github.com/617076674/Data-structure-and-algorithm-topic-set

原題連結:https://pintia.cn/problem-sets/15/problems/857

題目描述:

知識點:深度優先遍歷

思路:先建樹,再深度優先遍歷

用結構體file來作為樹的節點,其中包含char name[261]儲存檔名,bool型變數isDirectory表示是目錄還是檔案,bool型變數visited用來表示dfs過程中該檔案節點是否被訪問過,vector<file>型變數subFiles儲存其子目錄。

題目給的每個字串,表示的都是從root的第一個孩子開始的路徑。因此,我們用一個vector<file>型變數files儲存每個字串中的檔案值,依次將files中的檔案通過函式void add(file &f, int index)新增進以root為根的樹中。

void add(file &f, int index)函式的實現如下

注意,這個過程中我們會改變f檔案的subFile值,所以需要傳遞引用。

(1)如果index == files.size(),說明已經遍歷完了files中的所有檔案,直接return。

(2)遍歷f的子目錄,尋找與files[index]名字相同且同是檔案或同是目錄的檔案,如果找到,說明files[index]已經在f的子目錄中,我們考慮第index + 1個檔案,即遞迴地呼叫該函式add(f.subFiles[i], index + 1),並且返回。

(3)如果(2)過程沒有在f的子目錄中尋找到files[index],將files[index]加入f的子孩子中,並且遞迴地呼叫該函式add(f.subFiles[f.subFiles.size() - 1], index + 1)。

從root節點開始深度優先遍歷這棵檔案樹,並用int型level變數記錄空格數。

void dfs(file &nowVisit, int level)函式的實現如下

注意,這個過程中,我們會對f檔案的subFile進行排序,所以需要傳遞引用。

(1)如果當前檔案還未被訪問過,標記其已被訪問,並且對其subFile進行排序。

(2)輸出當前空格數和檔名。

(3)對其subFile裡的檔案,遞迴呼叫dfs函式,注意level需加2。

時間複雜度和空間複雜度均與題給的資料有關,很難計算。

C++程式碼:

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>

using namespace std;

struct file {
	char name[261];
	bool isDirectory, visited;
	vector<file> subFiles;
};

int N;
file root;
vector<file> files;

void add(file &f, int index);
bool cmp(file f1, file f2);
void dfs(file &nowVisit, int level);

int main() {
	scanf("%d", &N);
	strcpy(root.name, "root");
	root.isDirectory = true;
	root.visited = false;
	for(int i = 0; i < N; i++) {
		char line[270];
		scanf("%s", line);
		int j = 0;
		files.clear();
		while(j < strlen(line)) {
			char str[270];
			int point = 0;
			while(j < strlen(line) && line[j] != '\\') {
				str[point++] = line[j++];
			}
			str[point] = '\0';
			file f;
			if(j < strlen(line)) {
				f.isDirectory = true;
			} else {
				f.isDirectory = false;
			}
			f.visited = false;
			strcpy(f.name, str);
			files.push_back(f);
			j++;
		}
		add(root, 0);
	}
	dfs(root, 0);
	return 0;
}

void add(file &f, int index) {
	if(index == files.size()) {
		return;
	}
	for(int i = 0; i < f.subFiles.size(); i++){
		if(strcmp(f.subFiles[i].name, files[index].name) == 0 && f.subFiles[i].isDirectory == files[index].isDirectory) {
			add(f.subFiles[i], index + 1);
			return;
		}
	}
	f.subFiles.push_back(files[index]);
	add(f.subFiles[f.subFiles.size() - 1], index + 1);
}

bool cmp(file f1, file f2) {
	if(f1.isDirectory && !f2.isDirectory) {
		return true;
	} else if(!f1.isDirectory && f2.isDirectory) {
		return false;
	} else {
		return strcmp(f1.name, f2.name) < 0;
	}
}

void dfs(file &nowVisit, int level) {
	if(!nowVisit.visited) {
		nowVisit.visited = true;
		sort(nowVisit.subFiles.begin(), nowVisit.subFiles.end(), cmp);
	}
	printf("%*s%s\n", level, "", nowVisit.name);
	for(vector<file>::iterator it = nowVisit.subFiles.begin(); it != nowVisit.subFiles.end(); it++) {
		dfs(*it, level + 2);
	}
}

C++解題報告: