790 lines
29 KiB
C++
790 lines
29 KiB
C++
|
|
|
|
#ifndef __ZCPPMAIN__ZCSORT_LIST_H__
|
|
#define __ZCPPMAIN__ZCSORT_LIST_H__
|
|
|
|
|
|
/*////////////////////////////////////////////////////
|
|
|
|
■ CDoublieList.H 와 CObjList.H 가 include 한다.
|
|
|
|
-- 2013-04-30 22:57:00
|
|
|
|
////////////////////////////////////////////////////*/
|
|
|
|
|
|
#include "ZCppMain/ZMainHead.H"
|
|
|
|
|
|
namespace ZNsMain
|
|
{
|
|
|
|
// 양방향 연결리스트에 대한 정렬 클래스이다.
|
|
|
|
template<typename TTypObjList> 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
|
|
<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
static void QuickSort
|
|
(
|
|
TTypFuncIsMore APF_IsMore ,
|
|
TTypFuncIsLess APF_IsLess ,
|
|
ZCLink* APA_LinkPtrArr[],
|
|
TypeSize AL_FirstIndex ,
|
|
TypeSize AL_LastIndex
|
|
)
|
|
/*##################################################*/
|
|
{
|
|
if(AL_FirstIndex<AL_LastIndex)
|
|
{
|
|
TypeSize i=AL_FirstIndex ;
|
|
TypeSize j=AL_LastIndex+1 ;
|
|
|
|
ZCLink* VP_PivotLinkPtr=APA_LinkPtrArr[i];
|
|
|
|
do //////
|
|
{
|
|
while(AL_LastIndex >i && APF_IsLess(APA_LinkPtrArr[++i]->GetData(), VP_PivotLinkPtr->GetData()));
|
|
while(AL_FirstIndex<j && APF_IsMore(APA_LinkPtrArr[--j]->GetData(), VP_PivotLinkPtr->GetData()));
|
|
|
|
if(i<j) SwapLinkPtr(APA_LinkPtrArr[i], APA_LinkPtrArr[j]);
|
|
}
|
|
while(i<j);
|
|
|
|
/* SwapLinkPtr(APA_LinkPtrArr[AL_FirstIndex], APA_LinkPtrArr[j]);
|
|
|
|
위 코드 보다 아래처럼 2 줄로 쓰는게 별도의 스택 변수를 사용하지
|
|
않아서 좋다.
|
|
*/
|
|
APA_LinkPtrArr[AL_FirstIndex]=APA_LinkPtrArr[j];
|
|
APA_LinkPtrArr[j ]=VP_PivotLinkPtr ;
|
|
|
|
QuickSort(APF_IsMore, APF_IsLess, APA_LinkPtrArr, AL_FirstIndex, j-1 );
|
|
QuickSort(APF_IsMore, APF_IsLess, APA_LinkPtrArr, j+1, AL_LastIndex);
|
|
}/*
|
|
if(AL_FirstIndex<AL_LastIndex)*/
|
|
}/*
|
|
template
|
|
<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
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_FirstIndex<AL_LastIndex)
|
|
{
|
|
TypeSize i=AL_FirstIndex ;
|
|
TypeSize j=AL_LastIndex+1 ;
|
|
|
|
ZCLink* VP_PivotLinkPtr=APA_LinkPtrArr[i];
|
|
|
|
do ////
|
|
{
|
|
while(AL_LastIndex >i && APA_LinkPtrArr[++i]->GetData() < VP_PivotLinkPtr->GetData());
|
|
while(AL_FirstIndex<j && APA_LinkPtrArr[--j]->GetData() > VP_PivotLinkPtr->GetData());
|
|
|
|
if(i<j) SwapLinkPtr(APA_LinkPtrArr[i], APA_LinkPtrArr[j]);
|
|
}
|
|
while(i<j);
|
|
|
|
/* SwapLinkPtr(APA_LinkPtrArr[AL_FirstIndex], APA_LinkPtrArr[j]);
|
|
|
|
위 코드 보다 아래처럼 2 줄로 쓰는게 별도의 스택 변수를 사용하지 않아서 좋다.*/
|
|
|
|
APA_LinkPtrArr[AL_FirstIndex]=APA_LinkPtrArr[j];
|
|
APA_LinkPtrArr[j ]=VP_PivotLinkPtr ;
|
|
|
|
QuickSortAsc(APA_LinkPtrArr, AL_FirstIndex, j-1 );
|
|
QuickSortAsc(APA_LinkPtrArr, j+1, AL_LastIndex);
|
|
}/*
|
|
if(AL_FirstIndex<AL_LastIndex)*/
|
|
}/*
|
|
static void QuickSortAsc
|
|
(
|
|
ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex, TypeSize AL_LastIndex
|
|
)
|
|
/*####################*/
|
|
|
|
|
|
static void QuickSortDesc
|
|
(
|
|
ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex, TypeSize AL_LastIndex
|
|
)
|
|
/*#####################*/
|
|
{
|
|
if(AL_FirstIndex<AL_LastIndex)
|
|
{
|
|
TypeSize i=AL_FirstIndex ;
|
|
TypeSize j=AL_LastIndex+1;
|
|
|
|
ZCLink* VP_PivotLinkPtr=APA_LinkPtrArr[i];
|
|
|
|
do //////
|
|
{
|
|
while(AL_LastIndex >i && APA_LinkPtrArr[++i]->GetData() > VP_PivotLinkPtr->GetData());
|
|
while(AL_FirstIndex<j && APA_LinkPtrArr[--j]->GetData() < VP_PivotLinkPtr->GetData());
|
|
|
|
if(i<j) SwapLinkPtr(APA_LinkPtrArr[i], APA_LinkPtrArr[j]);
|
|
}
|
|
while(i<j);
|
|
|
|
/* SwapLinkPtr(APA_LinkPtrArr[AL_FirstIndex], APA_LinkPtrArr[j]);
|
|
|
|
위 코드 보다 아래처럼 2 줄로 쓰는게 별도의 스택 변수를 사용하지
|
|
않아서 좋다.
|
|
*/
|
|
APA_LinkPtrArr[AL_FirstIndex]=APA_LinkPtrArr[j];
|
|
APA_LinkPtrArr[j ]=VP_PivotLinkPtr ;
|
|
|
|
QuickSortDesc(APA_LinkPtrArr, AL_FirstIndex, j-1);
|
|
QuickSortDesc(APA_LinkPtrArr, j+1, AL_LastIndex);
|
|
}/*
|
|
if(AL_FirstIndex<AL_LastIndex)*/
|
|
}/*
|
|
static void QuickSortDesc
|
|
(
|
|
ZCLink* APA_LinkPtrArr[], TypeSize AL_FirstIndex, TypeSize AL_LastIndex
|
|
)
|
|
/*#####################*/
|
|
|
|
|
|
/*private:*/
|
|
public :
|
|
|
|
|
|
static void QuickSort(TTypObjList& ARR_CObjList, bool AB_IsAscending=true)
|
|
{
|
|
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(; i<VL_SortSize; ++i)
|
|
{
|
|
VPP_LinkPtrArr[i] =VP_TempLink;
|
|
VP_TempLink =VP_TempLink->GetNextPtr();
|
|
}/*
|
|
for(; i<VL_SortSize; ++i)*/
|
|
|
|
if(AB_IsAscending==true)
|
|
QuickSortAsc (VPP_LinkPtrArr, 0, VL_SortSize-1);
|
|
else QuickSortDesc(VPP_LinkPtrArr, 0, VL_SortSize-1);
|
|
|
|
for(i=1; i<VL_SortSize; ++i) // VL_SortSize-1 번 순환
|
|
{
|
|
ZCLink::JoinLink(VPP_LinkPtrArr[i-1], VPP_LinkPtrArr[i]);
|
|
}/*
|
|
//////////////////////////*/
|
|
|
|
ZCLink::MakeCircle
|
|
(VPP_LinkPtrArr[0], VPP_LinkPtrArr[VL_SortSize-1]);
|
|
|
|
ARR_CObjList.mp_HeadLink = VPP_LinkPtrArr[0];
|
|
|
|
delete[] VPP_LinkPtrArr; ////////////////////
|
|
}/*
|
|
static void QuickSort(TTypObjList& ARR_CObjList, bool AB_IsAscending=true)*/
|
|
|
|
|
|
template
|
|
<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
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(; i<VL_SortSize; ++i)
|
|
{
|
|
VPP_LinkPtrArr[i]=VP_TempLink;
|
|
VP_TempLink =VP_TempLink->GetNextPtr();
|
|
}/*
|
|
///////////////////////*/
|
|
|
|
QuickSort
|
|
(APF_IsMore, APF_IsLess, VPP_LinkPtrArr, 0, VL_SortSize-1);
|
|
|
|
for(i=1; i<VL_SortSize; ++i) // VL_SortSize-1 번 순환
|
|
{
|
|
ZCLink::JoinLink(VPP_LinkPtrArr[i-1], VPP_LinkPtrArr[i]);
|
|
}/*
|
|
//////////////////////////*/
|
|
|
|
ZCLink::MakeCircle
|
|
(VPP_LinkPtrArr[0], VPP_LinkPtrArr[VL_SortSize-1]);
|
|
|
|
ARR_CObjList.mp_HeadLink = VPP_LinkPtrArr[0];
|
|
|
|
delete[] VPP_LinkPtrArr; ////////////////////
|
|
}/*
|
|
template
|
|
<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
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<<std::endl<<"File : "<<__FILE__<<std::endl<<"Line : "<<__LINE__<<std::endl;
|
|
fileout<<"Error !! In static void QuickSortPart("<<endl
|
|
<<" TTypObjList& ARR_CObjList,"<<endl
|
|
<<" ZCLink* AP_HeadLink ,"<<endl
|
|
<<" TypeSize AL_HeadPos ,"<<endl
|
|
<<" ZCLink* AP_TailLink ,"<<endl
|
|
<<" TypeSize AL_TailPos ,"<<endl
|
|
<<" bool AB_IsAscending=true )"<<endl
|
|
<<"Parameters are not valid"<<endl;
|
|
fileout.close();
|
|
exit(1);
|
|
}/*
|
|
if(ARR_CObjList.IsEmpty()==true || ARR_CObjList.Find(AP_HeadLink)!=AL_HeadPos || ARR_CObjList.Find(AP_TailLink)!=AL_TailPos || AL_HeadPos>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(; i<VL_SortSize; ++i)
|
|
{
|
|
VPP_LinkPtrArr[i]=VP_TempLink;
|
|
VP_TempLink =VP_TempLink->GetNextPtr();
|
|
}/*
|
|
///////////////////////*/
|
|
|
|
if(AB_IsAscending==true)
|
|
QuickSortAsc (VPP_LinkPtrArr, 0, VL_SortSize-1);
|
|
else QuickSortDesc(VPP_LinkPtrArr, 0, VL_SortSize-1);
|
|
|
|
for(i=1; i<VL_SortSize; ++i) // VL_SortSize-1 번 순환
|
|
{
|
|
ZCLink::JoinLink(VPP_LinkPtrArr[i-1], VPP_LinkPtrArr[i]);
|
|
}/*
|
|
//////////////////////////*/
|
|
|
|
ZCLink::JoinLink(VP_PrevHead /*##########*/ , VPP_LinkPtrArr[0]);
|
|
ZCLink::JoinLink(VPP_LinkPtrArr[VL_SortSize-1], VP_NextTail );
|
|
|
|
if(AL_HeadPos==1)
|
|
ARR_CObjList.mp_HeadLink=VPP_LinkPtrArr[0];
|
|
|
|
delete[] VPP_LinkPtrArr; //////////////////////
|
|
}/*
|
|
static void QuickSortPart ############################
|
|
(
|
|
TTypObjList& ARR_CObjList,
|
|
ZCLink* AP_HeadLink ,
|
|
TypeSize AL_HeadPos ,
|
|
ZCLink* AP_TailLink ,
|
|
TypeSize AL_TailPos ,
|
|
bool AB_IsAscending=true
|
|
)
|
|
/*##################################################*/
|
|
|
|
|
|
static void MergeSort
|
|
(TTypObjList& ARR_AddList, TTypObjList& ARR_CutList, bool AB_IsAscending=true)
|
|
/*#################*/
|
|
{
|
|
/*/////////////////////////////////////////////////////////////////////////////
|
|
|
|
■ 연결리스트 ARR_AddList 와 ARR_CutList 는 이미 정렬되어 있는 것으로 간주하여
|
|
병합 정렬을 실시한다. ARR_CutList 의 앞 링크부터 차례로 끊어 ARR_AddList 의
|
|
적당한 링크에 삽입한다. 이 병합 정렬은 ARR_AddList 가 오름차순으로 정렬되어
|
|
있다면 ARR_CutList 도 오름차순으로 정렬되어 있어야 하고, AB_IsAscending 도
|
|
true 여야 원하는 결과를 얻을 수 있다.
|
|
|
|
/////////////////////////////////////////////////////////////////////////////*/
|
|
|
|
if( &ARR_AddList==&ARR_CutList ||
|
|
ARR_AddList.mp_HeadLink==0 ||
|
|
ARR_CutList.mp_HeadLink==0 ) return ;
|
|
|
|
/* 먼저 각 리스크를 삭제하는 신호를 보낸다. 진짜로 삭제하는 것은 아니지만,
|
|
링크를 이동시키는 과정에서 발생할 수 있는 에러를 막는데는 도움이 된다. */
|
|
|
|
ARR_AddList.OnDelete( ARR_AddList.mp_HeadLink, 1,
|
|
ARR_AddList.mp_HeadLink->mp_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<typename TFunctor> 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; i<VL_LoopSize; ++i)
|
|
{
|
|
if(VP_HeadLink->GetData()==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<VL_LoopSize; ++i)*/
|
|
}/*
|
|
template<typename TFunctor> 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; i<VL_LoopSize; ++i)
|
|
{
|
|
if(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<VL_LoopSize; ++i)*/
|
|
}/*
|
|
static void MakeUnique( #####################################
|
|
TTypObjList& ARR_CObjList ,
|
|
bool AB_IsSorted =false,
|
|
bool AB_IsAscending=true
|
|
############# ) ###########################################*/
|
|
|
|
|
|
template<typename TFunctor> 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<typename TFunctor> static void SplitGroup( ##########
|
|
TTypObjList& ARR_CObjList ,
|
|
TFunctor AR_Functor ,
|
|
bool AB_IsSorted=false ,
|
|
bool AB_IsAscending=true
|
|
############# ) ############################################*/
|
|
|
|
public:
|
|
};/*
|
|
template<typename TTypObjList> class ZtCSortObjList */
|
|
|
|
|
|
|
|
// 단방향 연결리스트에 대한 정렬 클래스이다.
|
|
|
|
template<typename TTypObjList> 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
|
|
<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
static void QuickSort
|
|
(
|
|
TTypFuncIsMore APF_IsMore ,
|
|
TTypFuncIsLess APF_IsLess ,
|
|
ZCLink* APA_LinkPtrArr[],
|
|
TypeSize AL_FirstIndex ,
|
|
TypeSize AL_LastIndex
|
|
)
|
|
/*##################################################*/
|
|
{
|
|
if(AL_FirstIndex<AL_LastIndex)
|
|
{
|
|
TypeSize i=AL_FirstIndex ;
|
|
TypeSize j=AL_LastIndex+1 ;
|
|
|
|
ZCLink* VP_PivotLinkPtr=APA_LinkPtrArr[i];
|
|
|
|
do //////
|
|
{
|
|
while(AL_LastIndex >i && APF_IsLess(APA_LinkPtrArr[++i]->GetData(), VP_PivotLinkPtr->GetData()));
|
|
while(AL_FirstIndex<j && APF_IsMore(APA_LinkPtrArr[--j]->GetData(), VP_PivotLinkPtr->GetData()));
|
|
|
|
if(i<j) SwapLinkPtr(APA_LinkPtrArr[i], APA_LinkPtrArr[j]);
|
|
}
|
|
while(i<j);
|
|
|
|
/* SwapLinkPtr(APA_LinkPtrArr[AL_FirstIndex],APA_LinkPtrArr[j]);
|
|
|
|
위 코드 보다 아래처럼 2 줄로 쓰는게 별도의 스택 변수를 사용하지
|
|
않아서 좋다.
|
|
*/
|
|
APA_LinkPtrArr[AL_FirstIndex]=APA_LinkPtrArr[j];
|
|
APA_LinkPtrArr[j ]=VP_PivotLinkPtr ;
|
|
|
|
QuickSort(APF_IsMore, APF_IsLess, APA_LinkPtrArr, AL_FirstIndex, j-1 );
|
|
QuickSort(APF_IsMore, APF_IsLess, APA_LinkPtrArr, j+1, AL_LastIndex);
|
|
}/*
|
|
if(AL_FirstIndex<AL_LastIndex)*/
|
|
}/*
|
|
template
|
|
<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
static void QuickSort
|
|
(
|
|
TTypFuncIsMore APF_IsMore ,
|
|
TTypFuncIsLess APF_IsLess ,
|
|
ZCLink* APA_LinkPtrArr[],
|
|
TypeSize AL_FirstIndex ,
|
|
TypeSize AL_LastIndex
|
|
)
|
|
/*##################################################*/
|
|
|
|
/*private:*/
|
|
public :
|
|
|
|
template
|
|
<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
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(; i<VL_SortSize; ++i)
|
|
{
|
|
VPP_LinkPtrArr[i]=VP_TempLink ;
|
|
VP_TempLink =VP_TempLink->GetNextPtr();
|
|
}
|
|
/////////////////////////
|
|
|
|
QuickSort(APF_IsMore, APF_IsLess, VPP_LinkPtrArr, 0, VL_SortSize-1);
|
|
|
|
for(i=1; i<VL_SortSize; ++i) // VL_SortSize-1 번 순환
|
|
{
|
|
ZCLink::JoinLink(VPP_LinkPtrArr[i-1], VPP_LinkPtrArr[i]);
|
|
}
|
|
////////////////////////////
|
|
|
|
#if(_CODE_OLD_) // 아래 코드만 빠진다.
|
|
ZCLink::MakeCircle(VPP_LinkPtrArr[0], VPP_LinkPtrArr[VL_SortSize-1]);
|
|
#else
|
|
ARR_CObjList.mp_HeadLink=VPP_LinkPtrArr[0] ;
|
|
ARR_CObjList.mp_TailLink=VPP_LinkPtrArr[VL_SortSize-1];
|
|
#endif
|
|
|
|
delete[] VPP_LinkPtrArr;
|
|
}/*
|
|
template<typename TTypFuncIsMore, typename TTypFuncIsLess>
|
|
static void QuickSort(TTypObjList& ARR_CObjList, TTypFuncIsMore APF_IsMore, TTypFuncIsLess APF_IsLess) */
|
|
|
|
public:
|
|
};/*
|
|
template<typename TTypObjList> class ZtCSortSimList */
|
|
|
|
}/*
|
|
namespace ZNsMain*/
|
|
|
|
|
|
#endif //__ZCPPMAIN__ZCSORT_LIST_H__
|