二叉樹-存儲硬盤目錄及文件,顯示文件大小,tree命令模仿(含全部代碼)

目錄

前言

樹轉二叉樹

全部代碼

結果截圖


前言

在cmd命令中有一個tree命令來顯示目錄及文件,類似下圖:

tree命令顯示

樹轉二叉樹

目錄及文件結構(左)及二叉樹保存(右)

其中,大寫字母的表示目錄,小寫字母的表示文件。根據左孩子右兄弟的規律,目錄下有文件或目錄則有左孩子,文件沒有左孩子,目錄XXX下的某個目錄或文件,若接下來目錄XXX還有其他目錄或文件,則有右孩子,否則沒有。

思路:之前寫過文章二叉樹基本操作函數(先、中、後、層次遍歷,含全部代碼), 我們將其改爲保存字符串的二叉樹,選擇先序遍歷函數,寫一個賦值函數,"#"代表爲NULL。另外,目錄下文件或目錄太多可能運行不出來,我們添加深度限制,減少遞歸深度,以上目錄的讀取順序爲:AAA BBB eee # FFF # # ccc # DDD ggg # # # #。

全部代碼

#include <iostream>
#include <io.h>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#define depth_limit 1   //開啓深度限制
#define max_depth 1     //最大深度2層
using namespace std;
//鏈式二叉樹數據結構
typedef struct BiTNode
{
	char data[100];//數據域,存放目錄及文件名
	struct BiTNode *lchild, *rchild;//左右孩子
}BiTNode, *BiTree;
int q = 0;
//創建二叉樹 規定數據域爲"#",則爲空 先序創建
void InitTree(BiTree &T, vector<string> files)
{
	if ("#" == files[q])
	{
		q++;
		T = NULL;
	}
	else {
		T = new BiTNode;
		strcpy_s(T->data,strlen(files[q].c_str())+1,files[q].c_str());
		q++;
		InitTree(T->lchild,files);
		InitTree(T->rchild,files);
	}
}

// 二叉樹賦值
void TreeAssign(BiTree &T,const char *path)
{
	if ("#" == path) T = NULL;
	else
	{
		T = new BiTNode;
		strcpy_s(T->data,strlen(path)+1,path);
	}
}

//二叉樹結點計算
int Count(BiTree T)
{
	if (T == NULL)
		return 0;
	else
		return 1 + Count(T->lchild) + Count(T->rchild);
}

//先序遍歷-遞歸
void PreOrder(BiTree T,int depth)
{
	if (T != NULL)
	{
		for (int j = 0; j < depth; j++) 
		{
			 if (j == depth - 1)
			{
				cout << "|______";
			}
			else
			cout << "      ";
		}
		cout << T->data<<endl;
		PreOrder(T->lchild,depth+1);//遞歸先序遍歷左右子樹
		PreOrder(T->rchild,depth);
	}
}

// 讀取文件大小
size_t GetFileSize(const std::string& file_name) {
	std::ifstream in(file_name.c_str());
	in.seekg(0, std::ios::end);
	size_t size = in.tellg();
	in.close();
	return size; //單位是:byte
}

//讀取所有目錄及文件 
void getAllFiles(string path, vector<string>& files, unsigned long long &filesize, int depth)
{
	//文件句柄  
	long   hFile = 0;
	//文件信息  
	struct _finddata_t fileinfo;  //很少用的文件信息讀取結構
	string p;  //string類很有意思的一個賦值函數:assign(),有很多重載版本
			   //有文件或目錄
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
	{
		do
		{
			if ((fileinfo.attrib &  _A_SUBDIR))  //比較文件類型是否是目錄
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
				{
					files.push_back(p.assign(fileinfo.name));
					if (depth_limit&&depth == max_depth)
					{
						files.push_back("#");
					}
					else
					{
						getAllFiles(p.assign(path).append("/").append(fileinfo.name), files, filesize, depth + 1);
					}
				}
			}
			else
			{
				files.push_back(p.assign(fileinfo.name));
				filesize += GetFileSize(p.assign(path).append("/").append(fileinfo.name));
				//文件沒有左孩子
				files.push_back("#");
			}
		} while (_findnext(hFile, &fileinfo) == 0);  //尋找下一個,成功返回0,否則-1
		_findclose(hFile);
		//目錄遍歷結束
		files.push_back("#");
	}
	//沒有文件或目錄
	else
	{
		files.push_back("#");
	}
}

//主函數
int main() {
	char * inPath = "F:/";
	vector<string> files;
	BiTree T;
	files.push_back(inPath);
	unsigned long long filesize = 0;
	getAllFiles(inPath, files, filesize,0);
	files.push_back("#");
	TreeAssign(T, inPath);
	TreeAssign(T->rchild, "#");
	InitTree(T, files);
	cout << "共" << Count(T) << "個目錄及文件," << "文件總大小爲" << filesize << "字節,目錄及文件如下:" << endl;
	PreOrder(T,0);
	return 0;
}

結果截圖

E盤2層深度顯示

更多數據結構與算法實現:數據結構(嚴蔚敏版)與算法的實現(含全部代碼)

有問題請下方評論,轉載請註明出處,並附有原文鏈接,謝謝!如有侵權,請及時聯繫。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章