데이터 구조 - 이 진 트 리 총화

47773 단어 데이터 구조 DS
데이터 구조 - 이 진 트 리 총화
  • 앞 에 써 주세요
  • 이 진 트 리 옮 겨 다 니 기
  • 재 귀 는 선, 중, 후 순 서 를 실현 한다
  • .
  • 비 재 귀적 달력
  • 선착순 비 재 귀
  • 중간 순서 비 재 귀
  • 후 순 비 재 귀
  • 차원 옮 겨 다 니 기
  • 이 진 트 리 복원
  • 선서 중 서 건 수
  • 후 서 중 서 건 수
  • 차원 중 서 건 수
  • 이 진 트 리 응용
  • 이 진 트 리 찾기
  • 밸 런 스 이 진 트 리 (AVL 트 리)
  • 및 수집
  • 더미
  • 하프 만 나무
  • 참고 자료
  • 앞 에 쓰다
  • 나무의 정의: 나 무 는 n (n > = 0) 개의 결점 의 유한 집합 이 고 n = 0 일 때 빈 나무 라 고 부른다.임의의 비 빈 나무 에서 만족 해 야 한다. ① 있 고 특정한 뿌리 라 고 불 리 는 결점 만 있다.② n 이 1 보다 크 면 나머지 결점 은 m (m > 0) 개의 서로 교차 하지 않 는 유한 한 집합 으로 나 눌 수 있 는데 그 중에서 모든 집합 자체 가 나무 이 고 뿌리 노드 의 나무 라 고 부른다.나 무 는 재 귀적 인 데이터 구조 이다.
  • 이 진 트 리 의 정의: 이 진 트 리 는 n (n > = 0) 개의 노드 의 유한 집합 이다. ① n = 0 시 빈 이 진 트 리 이다.② n > 0 시 한 개의 결점 과 두 개의 서로 교차 하지 않 는 뿌리 라 고 불 리 는 왼쪽 나무 와 오른쪽 나무 로 구성 된다.오른쪽 나무 와 왼쪽 나 무 는 각각 두 갈래 나무 다.이 진 트 리 는 질서 있 는 나무 로 좌우 나 무 를 뒤 집 으 면 다른 이 진 트 리 가 된다.
  • 이 진 트 리 와 도 2 의 질서 있 는 나무의 차이: ① 도 2 의 나 무 는 적어도 세 개의 결점 이 있 고 이 진 트 리 는 비어 있 을 수 있다.② 도 2 의 질서 있 는 나무의 아이 결점 의 좌우 순 서 는 상대 적 이 고 이 진 트 리 의 아이 결점 의 좌우 순 서 는 절대적 이다.

  • 두 갈래 나무 가 널 려 있다.
    이 진 트 리 의 옮 겨 다 니 는 것 은 일정한 순 서 를 통 해 이 진 트 리 의 모든 결점 을 방문 하 는 것 을 말한다.옮 겨 다 니 는 방법 은 보통 네 가지 가 있 습 니 다. 먼저 옮 겨 다 니 기, 중간 순서 옮 겨 다 니 기, 뒤의 순서 옮 겨 다 니 기, 그리고 차원 옮 겨 다 니 기, 그 중에서 앞의 세 가 지 는 보통 깊이 우선 검색 (DFS) 으로 이 루어 지고 차원 옮 겨 다 니 기 는 보통 넓 은 범위 우선 검색 (BFS) 으로 이 루어 집 니 다.또 앞의 세 가지 도 재 귀 를 통 해 이 루어 질 수 있다.
    재 귀적 으로 선, 중, 후 순 서 를 옮 겨 다 니 는 것 을 실현 하 다.
    void preOrder1(BinTree *root) //      
    {
    	if(root!=NULL)
    	{
    		cout<<root->data<<" ";
    		preOrder1(root->lchild);
    		preOrder1(root->rchild);
    	}
    }void inOrder1(BinTree *root) //      
    {
    	if(root!=NULL)
    	{
    		inOrder1(root->lchild);
    		cout<<root->data<<" ";
    		inOrder1(root->rchild);
    	}
    }void postOrder1(BinTree *root) //      
    {
    	if(root!=NULL)
    	{
    		postOrder1(root->lchild);
    		postOrder1(root->rchild);
    		cout<<root->data<<" ";
    	}
    }
    

    반복 되 지 않 음
    선서, 중 서, 후 서 는 스 택 을 통 해 비 재 귀 를 실현 하 는 것 이다.계층 사 이 를 옮 겨 다 니 는 것 은 대기 열 을 통 해 이 루어 집 니 다.
    우선 순위 비 재 귀
    void preOrder2(BinTree *root) //       
    {
        stack<BinTree*> s;
        BinTree *p=root;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                cout<<p->data<<" ";
                s.push(p);
                p=p->lchild;
            }
            if(!s.empty())
            {
                p=s.top();
                s.pop();
                p=p->rchild;
            }
        }
    }
    

    중간 순서 비 재 귀
    void inOrder2(BinTree *root) //       
    {
        stack<BinTree*> s;
        BinTree *p=root;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                s.push(p);
                p=p->lchild;
            }
            if(!s.empty())
            {
                p=s.top();
                cout<<p->data<<" ";
                s.pop();
                p=p->rchild;
            }
        }
    }
    

    후 순 비 재 귀
    여기에 두 가지 사고방식 이 있다.첫 번 째 는 뿌리 결산 점 이 왼쪽 아이 와 오른쪽 아이 가 방문 한 후에 야 방문 할 수 있 도록 하 는 것 이 므 로 어떤 결산 점 P 에 대해 서 는 먼저 창고 에 넣 어야 한다.P 가 왼쪽 아이 와 오른쪽 아이 가 존재 하지 않 는 다 면 직접 방문 할 수 있 습 니 다.또는 P 는 왼쪽 아이 나 오른쪽 아이 가 존재 하지만 왼쪽 아이 와 오른쪽 아이 가 모두 방문 되 었 으 면 이 노드 를 직접 방문 할 수 있 습 니 다.상기 두 가지 상황 이 아니라면 P 의 오른쪽 아이 와 왼쪽 아 이 를 순서대로 창고 에 넣 으 면 창고 꼭대기 요 소 를 찾 을 때마다 왼쪽 아이 가 오른쪽 아이 앞에서 방문 되 고 왼쪽 아이 와 오른쪽 아 이 는 모두 뿌리 노드 앞에서 방문 된다.
    void postOrder3(BinTree *root) //       
    {
        stack<BinTree*> s;
        BinTree *cur; //    
        BinTree *pre=NULL; //        
        s.push(root);
        while(!s.empty())
        {
            cur=s.top();
            if((cur->lchild==NULL&&cur->rchild==NULL)||
                    (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
            {
                cout<<cur->data<<" "; //                        
                s.pop();
                pre=cur;
            }
            else
            {
                if(cur->rchild!=NULL)
                    s.push(cur->rchild);
                if(cur->lchild!=NULL)
                    s.push(cur->lchild);
            }
        }
    }
    

    두 번 째 사고방식 은 임의의 결점 P 에 대해 창고 에 넣 은 다음 에 왼쪽 나 무 를 따라 왼쪽 아이의 결점 이 없 을 때 까지 계속 아래로 수색 하 는 것 이다. 이때 이 결점 은 창고 꼭대기 에 나타 나 지만 이 때 는 창고 에서 나 와 방문 할 수 없 기 때문에 오른쪽 아 이 는 방문 할 수 있다.그 다음 에 똑 같은 규칙 에 따라 오른쪽 트 리 를 똑 같이 처리 하고 오른쪽 아 이 를 방문 할 때 이 결산 점 은 스 택 꼭대기 에 나타 나 면 스 택 에서 나 와 방문 할 수 있 습 니 다.이렇게 하면 정확 한 방문 순 서 를 보장 할 수 있다.이 과정 에서 모든 결산 점 이 두 번 씩 스 택 꼭대기 에 나타 나 고 두 번 째 로 스 택 꼭대기 에 나타 날 때 만 방문 할 수 있 음 을 알 수 있다.따라서 이 결점 이 창고 꼭대기 에 처음 나타 난 것 인지 변 수 를 하나 더 설정 해 야 한다.
    void postOrder2(BinTree *root) //       
    {
    stack<BTNode*> s;
    BinTree *p=root;
    BTNode *temp;
    while(p!=NULL||!s.empty())
    {
    while(p!=NULL) //          ,            
    {
        BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
        btn->btnode=p;
        btn->isFirst=true;
        s.push(btn);
        p=p->lchild;
    }
    if(!s.empty())
    {
        temp=s.top();
        s.pop();
        if(temp->isFirst==true) //           
        {
            temp->isFirst=false;
            s.push(temp);
            p=temp->btnode->rchild;
        }
        else //        
        {
            cout<<temp->btnode->data<<" ";
            p=NULL;
        }
    }
    }
    }
    

    층 차 를 편력 하 다
    void LevelorderTraversal ( BinTree BT )
    {
        Queue Q;
        BinTree T;
        if ( !BT ) return; /*           */
         
        Q = CreatQueue(); /*      Q */
        AddQ( Q, BT );
        while ( !IsEmpty(Q) ) {
            T = DeleteQ( Q );
            printf("%d ", T->Data); /*           */
            if ( T->Left )   AddQ( Q, T->Left );
            if ( T->Right )  AddQ( Q, T->Right );
        }
    }
    

    이 진 트 리 복원
    이 진 트 리 복원 은 이 진 트 리 의 옮 겨 다 니 는 서열 에 따라 이 진 트 리 를 구성 하 는 것 을 말한다.이 진 트 리 를 복원 하 는 데 는 한 가지 결론 이 있다. 중 서 서열 은 선 서 서열, 후 서 서열, 차원 서열 중의 임 의 하나 와 유일한 이 진 트 리 를 구축 할 수 있 고 후 세 가 지 는 두 가 지 를 조합 하거나 세 가 지 를 함께 해도 유일한 이 진 트 리 를 구축 할 수 없다.그 이 유 는 먼저 순서, 후 순서, 차원 이 모두 뿌리 노드 를 제공 하고 역할 이 똑 같 으 며 모두 중간 순서 로 좌우 자 수 를 구분 해 야 하기 때문이다.
    선착순
    //                  
    Node preIn(int preL,int preH, int inL,int inH)
    {
        if(preL>preH)return NULL; //      ,      
        Node root = new node;
        root->data = pre[preL];
        int k=inL;
        for(k=inL;k<=inH;k++)
        {
            if(in[k]==pre[preL])
            {
                break;
            }
             }
        //      [preL+1,preL+k-inL],   [inL,k-1]
        root->left = preIn(preL+1,preL+k-inL,inL,k-1);
        //      [preL+k-inL+1,preH],   [k+1,inH].
        root->right = preIn(preL+k-inL+1,preH,k+1,inH);
        return root;     
    }
    int num=0;
    void postPrint(Node root)
    {
        if(root==NULL)return;
        postPrint(root->left);
        postPrint(root->right);
        post[num++]=root->data;
        return;
    }
    

    뒷 차례
    //                  
    
    Node postIn(int inL,int inH,int postL,int postH)
    {
        if(postL>postH)return NULL;
        Node root = new node;
        root->data = post[postH];
        int k= inL;
        for(k = inL;k<=inH;k++)
        {
            if(in[k]==post[postH])
            {
                break;
            }
        }
        //      [inL,k-1],   [postl,postL+k-inL-1]
        root->left = postIn(inL,k-1,postL,postL+k-inL-1);
        //      [k+1,inH] ,   [postL+k-inL,postH-1]
        root->right = postIn(k+1,inH,postL+k-inL,postH-1);
        return root;
    }
    
    void prePrint(Node root) //num initiate 0
    {
        if(root==NULL)return;
        pre[num++]=root->data;
        prePrint(root->left);
        prePrint(root->right);
        return;
    }
    

    계층
    //             
    Node levelIn(vector<int>layer,int inL,int inH)
    {
        if(layer.size()==0)return NULL;
        Node root = new node;
        root->data = layer[0];
        int k;
        for(k=inL;k<=inH;k++)
        {
            if(in[k]==layer[0])
            {
                break;
            }
        }
        vector<int>layerLeft;
        vector<int>layerRight;
        for(int i=1;i<layer.size();i++)
        {
            bool isLeft = false;
            for(int j=inL;j<k;j++)
            {
                if(layer[i]==in[j])
                {
                    isLeft = true;
                    break;
                }
            }
            if(isLeft)
            {
                layerLeft.push_back(layer[i]);
            }
            else
            {
                layerRight.push_back(layer[i]);
            }
        }
        
        root->left = levelIn(layerLeft,inL,k-1);
        root->right = levelIn(layerRight,k+1,inH);
        return root;
    }
    

    이 진 트 리 응용
    이 진 트 리 의 응용 은 주로 이 진 트 리 (BST), 균형 이 진 트 리 (AVL), 하 프 만 트 리, 쌓 기 및 집합 이 있다.
    두 갈래 찾기 트 리
    이 진 트 리 (Binary Search Tree) 는 특수 한 이 진 트 리 로 정렬 이 진 트 리, 이 진 트 리, 이 진 트 리 정렬 트 리 라 고도 부른다.그 재 귀 정 의 는 다음 과 같다. ① 또는 두 갈래 로 나 무 를 찾 는 것 은 빈 나무 이다.② 또는 이 진 트 리 는 뿌리 노드, 왼쪽 트 리, 오른쪽 트 리 로 구성 되 어 있 습 니 다. 그 중에서 왼쪽 트 리 와 오른쪽 트 리 는 모두 이 진 트 리 입 니 다. 그리고 왼쪽 트 리 의 모든 노드 의 데이터 도 메 인 은 뿌리 노드 의 데이터 도 메 인 보다 작 거나 같 습 니 다. 오른쪽 트 리 의 모든 노드 의 데이터 도 메 인 은 뿌리 노드 의 데이터 도 메 인 보다 큽 니 다.그 중에서 주의해 야 할 것 은 같은 숫자 라 도 삽입 순서 가 다 르 면 마지막 에 생 성 된 이 진 트 리 도 다르다 는 것 이다.또한, 이 진 트 리 는 실 용적 인 성질 을 가지 고 있 습 니 다. 이 진 트 리 를 중간 순서 로 옮 겨 다 니 며 옮 겨 다 니 는 결 과 는 질서 가 있 습 니 다.
    밸 런 스 이 진 트 리 (AVL 트 리)
    밸 런 스 이 진 트 리 는 옛 소련 의 두 수학자 가 제안 한 것 으로 AVL 트 리 라 고도 부른다.AVL 나 무 는 여전히 두 갈래 로 나 무 를 찾 고 있 으 며, 그 기초 위 에 '균형' 이라는 요 구 를 추 가 했 을 뿐이다.밸 런 스 란 AVL 트 리 의 임 의 결점 에 있어 서 왼쪽 트 리 와 오른쪽 트 리 의 높이 차 이 는 절대 1 을 넘 지 않 으 며, 이 가운데 좌우 트 리 의 높이 차 이 는 이 결점 의 밸 런 스 인자 라 고 한다.균형 인 자 는 서브 나무의 높이 를 빌려 간접 적 으로 구 할 수 있다.AVL 트 리 를 삽입 할 때 균형 을 맞 추기 위해 노드 를 조정 해 야 합 니 다. 구체 적 인 조정 상황 은 다음 과 같 습 니 다 (BF 는 균형 요 소 를 표시 합 니 다).
    나무형
    판정 조건
    조정 방법
    LL
    BF(root)=2,BF(root->lchild)=1
    루트 우회전
    LR
    BF(root)=2,BF(root->lchild)=-1
    루트 - > lchild 를 좌회전 하고 루트 를 우회전 합 니 다.
    RR
    BF(root)=-2,BF(root->rchild)=-1
    루트 좌회전
    RL
    BF(root)=-2,BF(root->rchild)=1
    루트 - > rchild 를 우회전 하고 루트 를 좌회전 합 니 다.
    병 찰 집
    그리고 집합 을 찾 는 것 은 집합 을 유지 하 는 데이터 구조 로 다음 과 같은 두 가지 조작 을 지원 합 니 다. ① 합병, 두 개의 집합 을 합 칩 니 다. ② 찾기: 두 요소 가 하나의 집합 에 있 는 지 판단 하고 집합 을 찾 는 것 은 하나의 배열 을 통 해 이 루어 집 니 다. 즉, int father [N] 입 니 다. 그 중에서 father [i] 는 요소 i 의 아버지 결점 을 나타 내 고 아버지 결점 자체 도 이 집합 안의 요소 입 니 다. 만약 father [i] 가= = i 는 원소 i 가 이 집합의 뿌리 결점 임 을 설명 하지만, 같은 집합 에 있어 서 는 하나의 뿌리 결점 만 존재 할 수 있 고, 이 를 소속 집합의 표식 으로 삼 을 수 있다. 또한 집합의 한 성질 을 조사한다. 같은 집합 에 서 는 반드시 고리 가 생기 지 않 는 다. 즉, 집합 이 발생 하 는 모든 집합 은 하나의 나무 이다.
    쌓다
    더 미 는 완전 이 진 트 리 로 나무 에 있 는 모든 노드 의 값 이 작 지 않다 (또는 크 지 않다).그 좌우 아이의 결점 의 값 은 이런 무 더 기 를 큰 무더기 라 고 부른다. 이때 모든 결점 의 값 은 그것 을 뿌리 결점 으로 하 는 자나무 의 최대 값 이다. 만약 에 아버지 결점 의 값 이 아이 결점 의 값 보다 작 거나 같 으 면 이런 무 더 기 를 작은 무더기 라 고 부른다. 이때 모든 결점 의 값 은 그것 을 뿌리 결점 으로 하 는 자나무 의 최소 값 이다.
    하프 만 나무
    루트 노드 에서 임의의 노드 까지 의 경로 길이 (지나 간 변수) 와 이 노드 의 가중치 곱 하기 를 이 노드 의 대역 권 경로 길이 라 고 합 니 다. 트 리 의 모든 잎 노드 의 대역 권 경로 길이 와 이 트 리 의 대역 권 경로 길이 (WPL) 라 고 합 니 다.. N 개의 잎 사 귀 노드 를 포함 하 는 이 진 트 리 중 권한 경로 길이 가 가장 작은 이 진 트 리 를 하 프 만 트 리 라 고도 부 르 고 가장 좋 은 이 진 트 리 라 고도 부른다.
    참고 자료
  • 왕도 포럼 조직 편집 전자 공업 출판사
  • (이 진 트 리 의 비 재 귀적 달력, 작가: 해자)https://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
  • 호 판 증 레이 편집장 기계 공업 출판사
  • 좋은 웹페이지 즐겨찾기