1. 程式人生 > >C語言二叉樹 遍歷目錄樹

C語言二叉樹 遍歷目錄樹

#include "stdio.h"
#include "windows.h"
#include <iostream>
using namespace std;
unsigned long sum = 0;
//////////////////////////////////////////////////////////////////////////
// 目錄樹連結串列結點定義
typedef struct _tFileTreeItem
{
    struct _tFileTreeItem* pPrevItem;   // 前一個單元
    struct _tFileTreeItem* pNextItem;   // 後一個單元
    struct _tFileTreeItem* pParentItem; // 父單元
    struct _tFileTreeItem* pChildItem;  // 子單元
    char FilePath[MAX_PATH];
    char FileName[MAX_PATH];
    unsigned long dwHashIndex;          // 索引序號
    int level;                          // 樹的深度
    int nNameLength;                    // 名稱長度
    char *strItemName;                  // 單元名稱,不包含路徑.(可變長度)
}FileTreeItem, *PFileTreeItem;

//////////////////////////////////////////////////////////////////////////
//查詢檔案或資料夾,儲存到樹中
void FindDir( FileTreeItem* TreeNode )
{
    WIN32_FIND_DATA fd;
    HANDLE hSearch;
    char filePathName[MAX_PATH];

    FileTreeItem* temp;
    FileTreeItem* tempnode;

    ZeroMemory( &fd, sizeof(WIN32_FIND_DATA) );
    ZeroMemory( filePathName, MAX_PATH );

    strcpy_s( filePathName, MAX_PATH, TreeNode->FilePath );

    if( filePathName[strlen(filePathName) - 1] != '\\' )
    {
        strcat_s( filePathName, MAX_PATH, "\\" );
        strcat_s( TreeNode->FilePath, MAX_PATH, "\\" );
    }
    strcat_s( filePathName, MAX_PATH, "*" );

    char* wcFilePathName = filePathName;
    hSearch = FindFirstFile( wcFilePathName, &fd );
    if ( hSearch != INVALID_HANDLE_VALUE )
    {
        if( (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
            && lstrcmp(fd.cFileName, ".") && lstrcmp(fd.cFileName,"..") )      
        {
            tempnode= new FileTreeItem;
            char *tempBuffer = fd.cFileName ;
            //儲存臨時節點的資訊
            tempnode->level = TreeNode->level + 1;
            strcpy_s( tempnode->FilePath, MAX_PATH, TreeNode->FilePath );
            strcat_s( tempnode->FilePath, MAX_PATH, tempBuffer );
            strcpy_s( tempnode->FileName, MAX_PATH, tempBuffer );

            tempnode->pPrevItem = NULL;
            tempnode->pNextItem = NULL;
            tempnode->pParentItem = NULL;
            tempnode->pChildItem = NULL;

            if( NULL == TreeNode->pChildItem )
            {// 根結點沒有孩子結點,這個就是第一個孩子結點了
                TreeNode->pChildItem = tempnode;
                tempnode->pPrevItem = tempnode->pNextItem = tempnode;// 雙向迴圈連結串列指標指向自身
            }
            else
            {// 將此結點插入到父結點指向的雙向迴圈連結串列中去
                temp = TreeNode->pChildItem;// 指向父結點的第一個孩子用來插入結點
                // 將此結點插入到第一個結點之前,即本級目錄樹的尾部【小技巧】
                tempnode->pNextItem = temp;
                tempnode->pPrevItem = temp->pPrevItem;
                temp->pPrevItem->pNextItem = tempnode;
                temp->pPrevItem = tempnode;
            }
            tempnode->pParentItem = TreeNode;// 指向父結點
            FindDir(tempnode);
        }
        while( FindNextFile(hSearch, &fd) )
        {
            if ( !lstrcmp(fd.cFileName, ".") || !lstrcmp(fd.cFileName,"..") )
            {
                continue;
            }
            else if ( (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) || (fd.dwFileAttributes ==48)
                && lstrcmp(fd.cFileName, ".") && lstrcmp(fd.cFileName,"..") )
            { 
                tempnode= new FileTreeItem;
                char *tempBuffer = fd.cFileName ;
                //儲存臨時節點的資訊
                tempnode->level = TreeNode->level + 1;
                strcpy_s( tempnode->FilePath, MAX_PATH, TreeNode->FilePath );
                strcat_s( tempnode->FilePath, MAX_PATH, tempBuffer );
                strcpy_s( tempnode->FileName, MAX_PATH, tempBuffer );

                tempnode->pPrevItem = NULL;
                tempnode->pNextItem = NULL;
                tempnode->pParentItem = NULL;
                tempnode->pChildItem = NULL;

                if( NULL == TreeNode->pChildItem )
                {// 根結點沒有孩子結點,這個就是第一個孩子結點了
                    TreeNode->pChildItem = tempnode;
                    tempnode->pPrevItem = tempnode->pNextItem = tempnode;// 雙向迴圈連結串列指標指向自身
                }
                else
                {// 將此結點插入到父結點指向的雙向迴圈連結串列中去
                    temp = TreeNode->pChildItem;// 指向父結點的第一個孩子用來插入結點
                    // 將此結點插入到第一個結點之前,即本級目錄樹的尾部【小技巧】
                    tempnode->pNextItem = temp;
                    tempnode->pPrevItem = temp->pPrevItem;
                    temp->pPrevItem->pNextItem = tempnode;
                    temp->pPrevItem = tempnode;
                }
                tempnode->pParentItem = TreeNode;// 指向父結點
                FindDir(tempnode);
            }
            else if ( lstrcmp( fd.cFileName, ".." ) && fd.dwFileAttributes != 48 )
            {// 此時存放的是檔案
                tempnode= new FileTreeItem;
                char *tempBuffer = fd.cFileName;
                //儲存臨時節點的資訊
                tempnode->level = TreeNode->level + 1;
                strcpy_s( tempnode->FilePath, MAX_PATH, TreeNode->FilePath );
                strcat_s( tempnode->FilePath, MAX_PATH, tempBuffer );
                strcpy_s( tempnode->FileName, MAX_PATH, tempBuffer );

                tempnode->pPrevItem = NULL;
                tempnode->pNextItem = NULL;
                tempnode->pParentItem = NULL;
                tempnode->pChildItem = NULL;

                if( NULL == TreeNode->pChildItem )
                {// 根結點沒有孩子結點,這個就是第一個孩子結點了
                    TreeNode->pChildItem = tempnode;
                    tempnode->pPrevItem = tempnode->pNextItem = tempnode;// 雙向迴圈連結串列指標指向自身
                }
                else
                {// 將此結點插入到父結點指向的雙向迴圈連結串列中去
                    temp = TreeNode->pChildItem;// 指向父結點的第一個孩子用來插入結點
                    // 將此結點插入到第一個結點之前,即本級目錄樹的尾部【小技巧】
                    tempnode->pNextItem = temp;
                    tempnode->pPrevItem = temp->pPrevItem;
                    temp->pPrevItem->pNextItem = tempnode;
                    temp->pPrevItem = tempnode;
                }
                tempnode->pParentItem = TreeNode;// 指向父結點
            }
        }
        FindClose(hSearch);
    }
}

//////////////////////////////////////////////////////////////////////////
//深度遍歷
void SearchTree(FileTreeItem* treeRoot)
{
    printf(treeRoot->FilePath);
    printf("\tlevel:%d.",treeRoot->level );
    printf("\n");
    sum++;

    if( (treeRoot->pChildItem != NULL) )
    {
        SearchTree( treeRoot->pChildItem );
    }

    if ( treeRoot->pNextItem != treeRoot->pParentItem->pChildItem )
    {
        SearchTree( treeRoot->pNextItem );
    }
}

void main()
{
    char* input_path= "e:\\";
    //初始化樹根節點
    DWORD dw_time_start  = GetTickCount();
    FileTreeItem *DirTreeRoot= new FileTreeItem;
    DirTreeRoot->level = 0; 
    strcpy_s( DirTreeRoot->FileName, strlen(DirTreeRoot->FileName), input_path );
    strcpy_s(DirTreeRoot->FilePath, strlen(DirTreeRoot->FilePath), input_path);
    DirTreeRoot->pPrevItem = NULL;
    DirTreeRoot->pNextItem = NULL;
    DirTreeRoot->pParentItem = DirTreeRoot;
    DirTreeRoot->pChildItem = NULL;     
    FindDir( DirTreeRoot );

    DWORD dw_time_end  = GetTickCount();
    DWORD dw_time_delta  = dw_time_end - dw_time_start;
   
    SearchTree(DirTreeRoot->pChildItem);
    cout << "目錄樹建立時間:" << dw_time_delta / 1000.0 << "秒." << endl;
    cout << "檔案和目錄的總數為:" << sum << endl;
    system( "pause" );
}