powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Алгоритм создания CDX файлов
2 сообщений из 27, страница 2 из 2
Алгоритм создания CDX файлов
    #36181807
Emery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
«Нелинейная» demo реализация сортировки естественным слиянием (Natural Merge Sort) на Visual FoxPro

Дан файловый источник Src (подразумевается достаточно большой DBF файл, который надо упорядочить по ключу (индексируемому полю) во внешний файл Buf1 или Buf2 , содержащих массив структур: индексируемое поле и номер его записи в Src . Операция Split определения упорядоченных подпследовательностей (УПП) в Src должна выполняться лишь однажды (в один проход) на Src , память под информацию об УПП если и отводиться то фиксированным количеством переменных, не зависящих от общего количества сортируемых ключей. Для удобства demo реализации алгоритма мы выбрали VFP , хотя конечный вариант будет написан на C++ . Вместо файлов взяты массивы памяти со случайным исходным набором чисел. Алгоритм сортировки также представлен следующим рисунком:



Заметим, что если отсутствует 13-я УПП в Src , то 3-я УПП в первом Buf2 , просто копируется во 2-ю УПП второго Buf1 .

А вот непосредственно код VFP, готовый для непосредственного выполнения:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
&& Demo «Non Lineal» Natural Merge Sort by Emery Emerald (C)  2009 

CLEAR 
SET TALK OFF
SET SAFETY OFF

CLOSE ALL
SET TEXTMERGE ON TO sort.txt NOSHOW

RAND( 7777777 )

KeyLen =  7 
Nmax =  100000 

\\Nmax = <<Nmax>>

IF Nmax <  1 
  MESSAGEBOX("Nmax < 1!")
  QUIT
ENDIF

DIMENSION Src[Nmax], Buf1[Nmax], Buf2[Nmax], Poses[ 32 ], Lens[ 32 ]

FOR i =  1  TO Nmax
  Src[i] = INT( 10 ^(KeyLen+ 1 )*RAND())% 10 ^KeyLen
ENDFOR

*!*	FOR i =  1  TO  32 
*!*	  Poses[i] =  0 
*!*	  Lens[i] =  0 
*!*	ENDFOR

*!*	FOR i =  1  TO Nmax
*!*	  Buf1[i] =  0 
*!*	  Buf2[i] =  0 
*!*	ENDFOR

i =  1 
j =  1 
NextPos =  1 
OldNextPos =  0 
Pos =  0 
OldPos =  0 
Len =  0 
OldLen =  0 
Sgn =  0 
OldSgn =  0 
LastSrcSgn =  0 
OutPos =  1 
IsEnd = .T.

&& Четные (парные) слияния
DO WHILE .T.
  IF NOT Split(@NextPos, @Len, @Sgn, @Src, @IsEnd)
    MESSAGEBOX("Error Split!")
    EXIT
  ENDIF

  IF(IsEnd)
    EXIT
  ENDIF

  LastSrcSgn = Sgn

  Pos = IIF(Sgn ==  1 , NextPos - Len, NextPos -  1 )

  IF(i% 2  ==  0 )
    FOR j =  1  TO INT(LOG(i)/LOG( 2 ))
      IF(i% 2 ^j ==  0 )
        OutPos = IIF(i ==  2 ^j,  1 , OutPos)
        
        In = IIF(j ==  1 , "Src", IIF(j% 2  ==  0 , "Buf1", "Buf2"))
        Out = IIF(j% 2  ==  0 , "Buf2", "Buf1")

        Pos = IIF(j >  1 , OldPos, Pos)
        Len = IIF(j >  1 , OldLen, Len)
        Sgn = IIF(j >  1 ,  1 , Sgn)
        OldSgn = IIF(j >  1 ,  1 , OldSgn)
        OutPos = IIF(j >  1 , Pos, OutPos)
        OldOutPos = OutPos
        
        IF NOT Merge(Pos, Len, Sgn, Poses[j], Lens[j], OldSgn, @OutPos, @&Out, @&In, @&In)
          MESSAGEBOX("Error Merge!")
          QUIT
        ENDIF

        OldPos = Poses[j+ 1 ]
        OldLen = Lens[j+ 1 ]
        OldSgn = Sgn
  
        Poses[j+ 1 ] = OldOutPos
        Lens[j+ 1 ] = Len + Lens[j]
        Sgn =  1 
      ENDIF
    ENDFOR
  ELSE    
    Poses[ 1 ] = Pos
    Lens[ 1 ] = Len
    OldSgn = Sgn
  ENDIF

  i = i +  1 
ENDDO

K = i -  1 
Q = j -  1 

Out = IIF(K ==  0 , "Src", IIF(j% 2  ==  0 , "Buf1", "Buf2"))

&& Нечетные (непарные) слияния
IF K <>  2 ^Q
  && Существует как минимум два числа q1 и q2, т.ч. K =  2 ^q1 +  2 ^q2

  && Находим первое из них (наименьшее)
  q1 =  0 
  FOR j =  0  TO  31 
    IF INT(K/ 2 ^j)% 2  ==  1 
      q1 = j
      EXIT 
    ENDIF
  ENDFOR

  IsQ1 = q1 >  0 
  q2 =  0 
  IsExit = .F.
  LastPos =  0 
  LastLen =  0 

  DO WHILE .T.
    && Находим второе из них
    FOR j = IIF(IsQ1, q1+ 1 , MAX(q1,  1 )) TO  31 
      P = INT(K/ 2 ^j)
      IF P% 2  ==  1 
        q2 = j
        EXIT 
      ENDIF
      
      IF P <  1 
        IsExit = .T.
        EXIT 
      ENDIF
    ENDFOR
    
    IF IsExit
      EXIT 
    ENDIF
    
    IsQ1 = .F.
    In1 = IIF(q1 ==  0 , "Src", IIF(q1% 2  ==  0 , "Buf2", "Buf1"))
    In2 = IIF(q2% 2  ==  0 , "Buf2", "Buf1")
    Out = IIF(q2% 2  ==  0 , "Buf1", "Buf2")
    Sgn = IIF(q1 >  0 ,  1 , LastSrcSgn)
    
    && Проверяем четность q1 и q2
    IF (q1 >  0 ) AND ((q1% 2  ==  0  AND q2% 2  ==  1 ) OR (q1% 2  ==  1  AND q2% 2  ==  0 ))
      In = IIF(q1 ==  0 , "Src", IIF(q1% 2  ==  0 , "Buf2", "Buf1"))
      Out = IIF(q2% 2  ==  0 , "Buf2", "Buf1")
    
      && Просто копируем УПП q1 в УПП q2
      Pos = Poses[q1+ 1 ]

      FOR j = Pos TO Pos + Lens[q1+ 1 ] -  1 
        Elem = &In[j]
        &Out[j] = Elem
      ENDFOR
      
      In1 = Out
      In2 = Out
      Out = IIF(q2% 2  ==  0 , "Buf1", "Buf2")
    ENDIF

    OutPos = Poses[q2+ 1 ]

    LastPos = IIF(LastPos ==  0 , Poses[q1+ 1 ], LastPos)
    LastLen = IIF(LastLen ==  0 , Lens[q1+ 1 ], LastLen)
    
    && Объединяем УПП q1 и q2
    IF NOT Merge(LastPos, LastLen, Sgn, Poses[q2+ 1 ], Lens[q2+ 1 ],  1 , @OutPos, @&Out, @&In1, @&In2)
      MESSAGEBOX("Error Merge!")
      QUIT
    ENDIF

    LastPos = Poses[q2+ 1 ]
    LastLen = Lens[q2+ 1 ] + LastLen

    q1 = q2 +  1 
  ENDDO
    
  Q = Q +  1 
ENDIF

\Количество УПП = <<IIF(K ==  0 ,  1 , K)>>
\

FOR i =  1  TO Nmax
  Elem = &Out[i]
  \<<PADL(ALLTRIM(STR(Elem)), KeyLen, " ")>>
ENDFOR

\
\Количество итераций = <<Q>>

CLOSE ALL
QUIT
***************************************************************************
FUNCTION Split
  PARAMETERS pPos, pLen, pSgn, pSrc, pIsEnd

  LOCAL i, j, k, l

  IF pPos <  1  OR pPos > Nmax
    pIsEnd = .T.
    RETURN .T.
  ENDIF
  
  IF Nmax ==  1 
    pPos =  2 
    pLen =  1 
    pSgn =  1 
    RETURN .T.
  ENDIF
  
  && Определяем тип порядка
  pSgn = IIF(pPos < Nmax, IIF(pSrc[pPos+ 1 ] < pSrc[pPos], - 1 ,  1 ),  1 )

  && Если пройдет весь цикл
  NewPos = Nmax +  1 
  NewLen = Nmax - pPos +  1 
  
  FOR i = pPos TO Nmax -  1 
    IF(pSgn ==  1  AND pSrc[i +  1 ] < pSrc[i]) OR (pSgn == - 1  AND pSrc[i +  1 ] >= pSrc[i])
      NewPos = i +  1 
      NewLen = Newpos - pPos
      pIsEnd = .F.
      EXIT
    ENDIF 
  ENDFOR
  
  pPos = NewPos
  pLen = NewLen
  RETURN .T.
ENDFUNC 
***************************************************************************
FUNCTION Merge
  PARAMETERS pPos1, pLen1, pSgn1, pPos2, pLen2, pSgn2, pOutPos, pDst, pSrc1, pSrc2

  IF pLen1 ==  0  OR pLen2 ==  0 
    RETURN .F.
  ENDIF 

  IF pPos1 <=  0  OR pPos2 <=  0  OR pOutPos <=  0 
    RETURN .F.
  ENDIF 

  LOCAL i, j, k, l

  i =  0 
  j =  0 

  DO WHILE i < pLen1 AND j < pLen2
    LVal = pSrc1[pPos1 + pSgn1*i]
    RVal = pSrc2[pPos2 + pSgn2*j]
    
    IF LVal <= RVal
      pDst[pOutPos] = LVal
      i = i +  1 
      pOutPos = pOutPos +  1 
    ENDIF 
    
    IF LVal >= RVal
      pDst[pOutPos] = RVal
      j = j +  1 
      pOutPos = pOutPos +  1 
    ENDIF 
  ENDDO
    
  * Дописываем остаток, если он есть
      
  IF i < pLen1
    FOR l = i TO pLen1 -  1 
      pDst[pOutPos] = pSrc1[pPos1 + pSgn1*l]
      pOutPos = pOutPos +  1 
    ENDFOR 
  ENDIF
  
  IF j < pLen2
    FOR l = j TO pLen2 -  1 
      pDst[pOutPos] = pSrc2[pPos2 + pSgn2*l]
      pOutPos = pOutPos +  1 
    ENDFOR 
  ENDIF

  RETURN .T.
ENDFUNC
***************************************************************************
***************************************************************************
...
Рейтинг: 0 / 0
Алгоритм создания CDX файлов
    #36412421
Emery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
2 сообщений из 27, страница 2 из 2
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Алгоритм создания CDX файлов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]