#ifndef __ZCPPMAIN__ZCSORT_LIST_H__ #define __ZCPPMAIN__ZCSORT_LIST_H__ /*//////////////////////////////////////////////////// ■ CDoublieList.H 와 CObjList.H 가 include 한다. -- 2013-04-30 22:57:00 ZtCArray.H 와 ZtCObjList.H 가 include 한다. -- 2025-08-17 14:37:00 현재는 ZtCArray.H 와 ZtCObjList.H 를 include 한다. -- 2025-08-17 15:42:00 ////////////////////////////////////////////////////*/ #include "ZCppMain/ZtCArray.H" #include "ZCppMain/ZtCObjList.H" namespace ZNsMain { // 양방향 연결리스트에 대한 정렬 클래스이다. template class ZtCSortObjList { public : typedef typename TTypObjList::ZCLink ZCLink ; typedef typename TTypObjList::TypeData TypeData; typedef typename TTypObjList::TypeArg TypeArg ; typedef typename TTypObjList::TypeSize TypeSize; private: static inline bool IsMore(TypeArg AR_LeftType, TypeArg AR_RightType) { /* IsMore() 함수와 IsLess() 는 QuickSort() 멤버 함수에서 쓰는 함수 포인터에 대입하기 위해서 정의하였다. */ return AR_LeftType > AR_RightType ; }/* static inline bool IsMore(TypeArg AR_LeftType, TypeArg AR_RightType)*/ static inline bool IsLess(TypeArg AR_LeftType, TypeArg AR_RightType) { return AR_LeftType < AR_RightType ; }/* static inline bool IsLess(TypeArg AR_LeftType, TypeArg AR_RightType)*/ static inline void SwapLinkPtr(ZCLink*& APR_LinkI, ZCLink*& APR_LinkJ) { ZCLink* VP_Temp=APR_LinkI; APR_LinkI=APR_LinkJ; APR_LinkJ=VP_Temp; }/* static inline void SwapLinkPtr( ZCLink*& APR_LinkI, ZCLink*& APR_LinkJ) */ template static void QuickSort ( TTypFuncIsMore APF_IsMore , TTypFuncIsLess APF_IsLess , ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex , TypeSize AL_LastIndex ) /*##################################################*/ { if(AL_FirstIndexi && APF_IsLess(APA_LinkPtrArr[++i]->GetData(), VP_PivotLinkPtr->GetData())); while(AL_FirstIndexGetData(), VP_PivotLinkPtr->GetData())); if(i static void QuickSort ( TTypFuncIsMore APF_IsMore , TTypFuncIsLess APF_IsLess , ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex , TypeSize AL_LastIndex ) ###########################################################*/ static void QuickSortAsc ( ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex, TypeSize AL_LastIndex ) /*####################*/ { if(AL_FirstIndexi && APA_LinkPtrArr[++i]->GetData() < VP_PivotLinkPtr->GetData()); while(AL_FirstIndexGetData() > VP_PivotLinkPtr->GetData()); if(ii && APA_LinkPtrArr[++i]->GetData() > VP_PivotLinkPtr->GetData()); while(AL_FirstIndexGetData() < VP_PivotLinkPtr->GetData()); if(iGetNextPtr(); }/* for(; i static void QuickSort ( TTypObjList& ARR_CObjList , TTypFuncIsMore APF_IsMore , TTypFuncIsLess APF_IsLess ) ////////////////////////////////////////////////////// { if(ARR_CObjList.GetSize()<=1) return; TypeSize VL_SortSize = ARR_CObjList.GetSize() ; ZCLink** VPP_LinkPtrArr= new ZCLink*[VL_SortSize]; if(VPP_LinkPtrArr==0) { // Add codes for memory over return; }/* if(VPP_LinkPtrArr==0)*/ ZCLink* VP_TempLink = ARR_CObjList.GetHeadLinkPtr(); TypeSize i=0 ; for(; iGetNextPtr(); }/* ///////////////////////*/ QuickSort (APF_IsMore, APF_IsLess, VPP_LinkPtrArr, 0, VL_SortSize-1); for(i=1; i static void QuickSort ( TTypObjList& ARR_CObjList , TTypFuncIsMore APF_IsMore , TTypFuncIsLess APF_IsLess ) ////////////////////////////////////////////////////*/ static void QuickSortPart /*########################*/ ( TTypObjList& ARR_CObjList, ZCLink* AP_HeadLink , TypeSize AL_HeadPos , ZCLink* AP_TailLink , TypeSize AL_TailPos , bool AB_IsAscending=true ) /*##################################################*/ { // AP_HeadLink 부터 AP_TailLink 까지만 정렬 #ifdef _DEBUG if(ARR_CObjList.IsEmpty()==true || ARR_CObjList.Find(AP_HeadLink)!=AL_HeadPos || ARR_CObjList.Find(AP_TailLink)!=AL_TailPos || AL_HeadPos>AL_TailPos) { std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app); fileout<AL_TailPos)*/ #endif //_DEBUG if(AL_HeadPos==1 && AL_TailPos==ARR_CObjList.GetSize()) { QuickSort(ARR_CObjList, AB_IsAscending); return; }/* if(AL_HeadPos==1 && AL_TailPos==ARR_CObjList.GetSize())*/ ZCLink* VP_PrevHead=AP_HeadLink->GetPrevPtr(); ZCLink* VP_NextTail=AP_TailLink->GetNextPtr(); TypeSize VL_SortSize=AL_TailPos-AL_HeadPos+1 ; ZCLink** VPP_LinkPtrArr = new ZCLink*[VL_SortSize]; if(VPP_LinkPtrArr==0) { // Add codes for memory over return; }/* if(VPP_LinkPtrArr==0)*/ ZCLink* VP_TempLink = AP_HeadLink; TypeSize i=0; for(; iGetNextPtr(); }/* ///////////////////////*/ if(AB_IsAscending==true) QuickSortAsc (VPP_LinkPtrArr, 0, VL_SortSize-1); else QuickSortDesc(VPP_LinkPtrArr, 0, VL_SortSize-1); for(i=1; imp_PrevLink, ARR_AddList.ml_Size ); ARR_CutList.OnDelete( ARR_CutList.mp_HeadLink, 1, ARR_CutList.mp_HeadLink->mp_PrevLink, ARR_CutList.ml_Size ); bool (*pf_IsTrueValue)(TypeArg AR_Left,TypeArg rRigh); if(AB_IsAscending==true) pf_IsTrueValue=IsMore; else pf_IsTrueValue=IsLess; if(pf_IsTrueValue(ARR_AddList.GetTailData(), ARR_CutList.GetHeadData())==false) { ARR_AddList.JoinTail(ARR_CutList); return; // 이때는 더 이상 비교할 필요가 없다. }/* if(pf_IsTrueValue(ARR_AddList.GetTailData(), ARR_CutList.GetHeadData())==false)*/ ZCLink* VP_LhsTail =ARR_AddList.mp_HeadLink->mp_PrevLink; ZCLink* VP_LhsTemp =ARR_AddList.mp_HeadLink; ZCLink* VP_RhsHead =ARR_CutList.mp_HeadLink; TypeSize VL_LhsTempPos=1 ; // VP_LhsTemp 의 위치 bool VB_IsMoved =false; ZCLink* VP_TempLink =0 ; do ////// { if(pf_IsTrueValue(VP_LhsTemp->GetData(), VP_RhsHead->GetData())==true) { VP_TempLink=VP_RhsHead ; VP_RhsHead =VP_RhsHead->mp_NextLink; ARR_AddList.JoinBefore //////////////////// ( ARR_CutList.CutLink(VP_TempLink,1), VP_LhsTemp, VL_LhsTempPos ); /////////////////////////////////////////// /* VP_LhsTemp 앞에 링크가 하나 삽입되었으므로, VP_LhsTemp 의 위치값을 하나 증가시킨다. */ ++VL_LhsTempPos; VB_IsMoved=true; }/* if(pf_IsTrueValue(VP_LhsTemp->GetData(), VP_RhsHead->GetData())==true)*/ if(ARR_CutList.mp_HeadLink==0) return; if(VP_LhsTemp==VP_LhsTail) { ARR_AddList.JoinTail(ARR_CutList); return; }/* if(VP_LhsTemp==VP_LhsTail)*/ if(VB_IsMoved==false) { VP_LhsTemp=VP_LhsTemp->mp_NextLink; ++VL_LhsTempPos; } else { VB_IsMoved=false; } } while(true); }/* static void MergeSort (TTypObjList& ARR_AddList, TTypObjList& ARR_CutList, bool AB_IsAscending=true) /*#################*/ template void MakeUnique( /*############*/ TTypObjList& ARR_CObjList , TFunctor AR_Functor , bool AB_IsSorted =false, bool AB_IsAscending=true /*#########*/ ) /*#########################################*/ { // ARR_CObjList 의 각 노드를 유일하게 만든다. if(AB_IsSorted==false) QuickSort(ARR_CObjList,AB_IsAscending); TypeSize VL_LoopSize= ARR_CObjList.GetSize() ; TypeSize VL_Index = 1 ; ZCLink* VP_HeadLink= ARR_CObjList.GetHeadLinkPtr(); ZCLink* VP_CutLink = 0 ; /* VL_LoopSize-1 번 순환하며 같은 원소가 이웃한다면 앞뒤 노드에 대해 어떤 처리를 하고 뒤쪽의 노드를 삭제한다. */ for(TypeSize i=1; iGetData()==VP_HeadLink->GetNextPtr()->GetData()) { AR_Functor ////////////////////////// ( VP_HeadLink->GetData(), VP_HeadLink->GetNextPtr()->GetData() ); VP_CutLink=VP_HeadLink->GetNextPtr(); ARR_CObjList.Delete(VP_CutLink, VL_Index+1); } else { (VP_HeadLink=VP_HeadLink->GetNextPtr(), ++VL_Index); } }/* for(TypeSize i=1; i void MakeUnique( ################ TFunctor AR_Functor , bool AB_IsSorted=false , bool AB_IsAscending=true ################# ) #######################################*/ static void MakeUnique( /*#################################*/ TTypObjList& ARR_CObjList , bool AB_IsSorted =false, bool AB_IsAscending=true /*#########*/ ) /*#########################################*/ { // ARR_CObjList 의 각 노드를 유일하게 만든다. if(AB_IsSorted==false) QuickSort(ARR_CObjList,AB_IsAscending); TypeSize VL_LoopSize =ARR_CObjList.GetSize() ; TypeSize VL_Index =1 ; ZCLink* VP_HeadLink =ARR_CObjList.GetHeadLinkPtr(); ZCLink* VP_CutLink =0 ; /* VL_LoopSize-1 번 순환하며 같은 원소가 이웃한다면 뒤쪽의 노드를 삭제한다. */ for(TypeSize i=1; iGetData()==VP_HeadLink->GetNextPtr()->GetData()) { VP_CutLink = VP_HeadLink->GetNextPtr() ; ARR_CObjList.Delete(VP_CutLink, VL_Index+1); } else { (VP_HeadLink=VP_HeadLink->GetNextPtr(), ++VL_Index); } }/* for(TypeSize i=1; i static void SplitGroup( /*#####*/ TTypObjList& ARR_CObjList , TFunctor AR_Functor , bool AB_IsSorted =false, bool AB_IsAscending=true /*#########*/ ) /*#########################################*/ { /* ARR_CObjList 의 각 노드를 같은 것끼리 그룹으로 묵어서 묶여진 리스트에 대해 AR_Functor 를 수행한다. */ if(ARR_CObjList.IsEmpty()) return; if(AB_IsSorted==false) { QuickSort(ARR_CObjList, AB_IsAscending); // 정렬이 안되었으면 정렬을 하고... }/* if(AB_IsSorted==false)*/ TypeSize VL_LoopSize=ARR_CObjList.GetSize() ; TypeSize VL_TailPos =1 ; ZCLink* VP_CutHead =ARR_CObjList.GetHeadLinkPtr(); ZCLink* VP_CutTail =VP_CutHead ; ZCLink* VP_CutTemp =VP_CutTail->GetNextPtr() ; // VL_LoopSize-1 번 순환 for(TypeSize i=2; i<=VL_LoopSize; ++i) { if(VP_CutTail->GetData()==VP_CutTemp->GetData()) { VP_CutTail=VP_CutTemp ; VP_CutTemp=VP_CutTemp->GetNextPtr() ; ++VL_TailPos; } else // VP_CutTail->GetData()!=VP_CutTemp->GetData() { /* 다음 노드와 다르면 이전 노드들은 서로 같다는 것이다. 이전 노드들은 functor 로 처리를 넘긴다. functor 는 넘겨받은 리스트를 반드시 써야(삭제해야) 한다. CutLink() 멤버 함수는 내부에 정적 리스트 개체를 가지고 있는데 여기에 쓸데없는 자료가 남겨져서는 안되기 때문이다. */ AR_Functor ////////////////////////////////////// ( ARR_CObjList.CutLink ( VP_CutHead, 1, VP_CutTail, VL_TailPos ) ); ///////////////////////////////////////////////// VP_CutHead =VP_CutTemp; VP_CutTail =VP_CutTemp; VP_CutTemp =VP_CutTemp->GetNextPtr(); VL_TailPos =1 ; }/* else // VP_CutTail->GetData()!=VP_CutTemp->GetData()*/ }/* for(TypeSize i=2; i<=VL_LoopSize; ++i)*/ if(ARR_CObjList.IsEmpty()==false) AR_Functor(ARR_CObjList); }/* template static void SplitGroup( ########## TTypObjList& ARR_CObjList , TFunctor AR_Functor , bool AB_IsSorted=false , bool AB_IsAscending=true ############# ) ############################################*/ public: };/* template class ZtCSortObjList */ namespace ZNsExam { template class ZtCSortIntList { public: static void ShowElemnet(int AI_Element) { cout<<"* Element : "< CObjList ; CObjList VO_CIntList; ////////////////////////// VO_CIntList.AddTail(10); VO_CIntList.AddTail(1 ); VO_CIntList.AddTail(6 ); VO_CIntList.AddTail(4 ); VO_CIntList.AddTail(7 ); VO_CIntList.AddTail(2 ); VO_CIntList.AddTail(8 ); VO_CIntList.AddTail(5 ); VO_CIntList.AddTail(9 ); VO_CIntList.AddTail(3 ); cout<<"# Sort ASC" <:: QuickSort(RR(VO_CIntList), true ); VO_CIntList.IterElement(ShowElemnet); cout<<"# Sort DESC"<:: QuickSort(RR(VO_CIntList), false); VO_CIntList.IterElement(ShowElemnet); return 0 ; }/* static int Main(int AI_ArgCnt=0, const char* APP_ArgVal[]=0)*/ public: };/* template class ZtCSortIntList*/ }/* namespace ZNsExam*/ // 단방향 연결리스트에 대한 정렬 클래스이다. template class ZtCSortSimList { public : typedef typename TTypObjList::ZCLink ZCLink ; typedef typename TTypObjList::TypeData TypeData ; typedef typename TTypObjList::TypeArg TypeArg ; typedef typename TTypObjList::TypeSize TypeSize ; private: static inline void SwapLinkPtr(ZCLink*& APR_LinkI, ZCLink*& APR_LinkJ) { ZCLink* VP_Temp =APR_LinkI; APR_LinkI=APR_LinkJ; APR_LinkJ=VP_Temp; }/* static inline void SwapLinkPtr( ZCLink*& APR_LinkI, ZCLink*& APR_LinkJ) */ template static void QuickSort ( TTypFuncIsMore APF_IsMore , TTypFuncIsLess APF_IsLess , ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex , TypeSize AL_LastIndex ) /*##################################################*/ { if(AL_FirstIndexi && APF_IsLess(APA_LinkPtrArr[++i]->GetData(), VP_PivotLinkPtr->GetData())); while(AL_FirstIndexGetData(), VP_PivotLinkPtr->GetData())); if(i static void QuickSort ( TTypFuncIsMore APF_IsMore , TTypFuncIsLess APF_IsLess , ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex , TypeSize AL_LastIndex ) /*##################################################*/ /*private:*/ public : template static void QuickSort ( TTypObjList& ARR_CObjList, TTypFuncIsMore APF_IsMore , TTypFuncIsLess APF_IsLess ) /*##################################################*/ { if(ARR_CObjList.GetSize()<=1) return; TypeSize VL_SortSize = ARR_CObjList.GetSize() ; ZCLink** VPP_LinkPtrArr = new ZCLink*[VL_SortSize]; if(VPP_LinkPtrArr==0) { // Add codes for memory over return; }/* if(VPP_LinkPtrArr==0)*/ ZCLink* VP_TempLink = ARR_CObjList.GetHeadLinkPtr(); TypeSize i=0 ; for(; iGetNextPtr(); } ///////////////////////// QuickSort(APF_IsMore, APF_IsLess, VPP_LinkPtrArr, 0, VL_SortSize-1); for(i=1; i static void QuickSort(TTypObjList& ARR_CObjList, TTypFuncIsMore APF_IsMore, TTypFuncIsLess APF_IsLess) */ public: };/* template class ZtCSortSimList */ }/* namespace ZNsMain*/ #endif //__ZCPPMAIN__ZCSORT_LIST_H__