home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Best Objectech Shareware Selections
/
UNTITLED.iso
/
boss
/
word
/
text
/
024
/
sort.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-04
|
24KB
|
725 lines
/*
* These functions sort lines according to keys in a marked BOX block.
*
* Being that the data structure was changed from a big text buffer to a
* linked list, we can replace the simple insertion sort algorithm with a
* much faster sort algorithm. The classic search and sort reference is by
* Donald E. Knuth, _The Art of Computer Programming; Volume 3: Sorting and
* Searching_. One of the fastest and most widely used general purpose
* sorting algorithms is the "Quicksort" algorithm.
*
* For implementation hints and guidelines on the Quicksort algorithm, one
* might read the original Quicksort paper by C. A. R. Hoare or anything
* by Robert Sedgewick. Although Dr. Sedgewick includes a chapter on
* Quicksort in his intro computer science textbooks, _Algorithms in X_,
* I prefer the detailed hints and guidelines in his 1978 CACM paper.
* Incidentally, Dr. Sedgewick's Ph.D. dissertation was on the modification
* and mathematical analysis of the Quicksort algorithm.
*
*
* See:
*
* Charles Antony Richard Hoare, "Algorithm 63: Partition." _Communications
* of the ACM_, 4 (No. 7): 321, 1961.
*
* Charles Antony Richard Hoare, "Algorithm 64: Quicksort." _Communications
* of the ACM_, 4 (No. 7): 321, 1961.
*
* Charles Antony Richard Hoare, "Quicksort." _The Computer Journal_,
* 5 (April 1962 - January 1963): 10-15, 1962.
*
* See also:
*
* Donald Ervin Knuth, _The Art of Computer Programming; Volume 3: Sorting
* and Searching_, Addison-Wesley, Reading, Mass., 1973, Chapter 5,
* Sorting, pp 114-123. ISBN 0-201-03803-X.
*
* Robert Sedgewick, "Implementing Quicksort Programs." _Communications
* of the ACM_, 21 (No. 10): 847-857, 1978.
*
*
* Quicksort in TDE
*
* Quicksort in TDE is a stable, non-recursive implementation based on
* Program 2, page 851, CACM, 21 (No. 10), 1978, by Robert Sedgewick. My
* partition algorithm finds the median-of-three. Then, it walks from the
* head of the list, comparing nodes, and uses the first occurrence of the
* key of the median-of-three as the partition node. Mostly by accident
* and partly by design, my partition routine uses a "fat pivot" to keep
* equal nodes in the same relative order as they appear in the file (the
* definition of a stable sort). By using the first median-of-three node
* as the partitioning node, 1) sorting a sorted list is fairly fast and
* 2) encountering a worst case is very unlikely. TDE will sort, fairly
* fast, multiple keys ascending or descending, ignore or match case, and
* preserve order in the file, while using a custom sort sequence for your
* favorite domestic or foreign language.
*
*
* New editor name: TDE, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991, version 1.0
* Date: July 29, 1991, version 1.1
* Date: October 5, 1991, version 1.2
* Date: January 20, 1992, version 1.3
* Date: February 17, 1992, version 1.4
* Date: April 1, 1992, version 1.5
* Date: June 5, 1992, version 2.0
* Date: October 31, 1992, version 2.1
* Date: April 1, 1993, version 2.2
* Date: June 5, 1993, version 3.0
*
* This code is released into the public domain, Frank Davis.
* You may use and distribute it freely.
*/
#include "tdestr.h"
#include "common.h"
#include "tdefunc.h"
#include "define.h"
/*
* Name: sort_box_block
* Purpose: sort lines according to text in marked BOX block
* Date: June 5, 1992
* Passed: window: pointer to current window
* Notes: quick sort and insertion sort the lines in the BOX buff according
* to stuff in a box block.
*/
int sort_box_block( WINDOW *window )
{
int prompt_line;
int block_type;
line_list_ptr ll;
register file_infos *file;
WINDOW *sw;
int rc;
char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
/*
* make sure block is marked OK
*/
rc = OK;
prompt_line = window->bottom_line;
entab_linebuff( );
if (un_copy_line( window->ll, window, TRUE ) == ERROR)
return( ERROR );
check_block( );
if (g_status.marked == TRUE) {
file = g_status.marked_file;
block_type = file->block_type;
if (block_type == BOX) {
/*
* sort ascending or descending?
*/
rc = get_sort_order( window );
if (rc != ERROR) {
file->modified = TRUE;
if (mode.do_backups == TRUE) {
sw = g_status.window_list;
for (; ptoul( sw->file_info ) != ptoul( file );)
sw = sw->next;
backup_file( sw );
}
/*
* figure the width of the block.
*/
sort.block_len = file->block_ec + 1 - file->block_bc;
/*
* save the prompt line and print the quicksort message.
*/
save_screen_line( 0, prompt_line, line_buff );
eol_clear( 0, prompt_line, g_display.text_color );
set_prompt( block22a, prompt_line );
/*
* set up the sort structure.
*/
sort.bc = g_status.marked_file->block_bc;
sort.ec = g_status.marked_file->block_ec;
sort.order_array = (mode.search_case == IGNORE) ?
sort_order.ignore : sort_order.match;
/*
* save the previous node for use with insertion sort.
*/
ll = file->block_start->prev;
quick_sort_block( file->block_br, file->block_er,
file->block_start, file->block_end );
/*
* get back previous node and clean up list with insertion
* sort.
*/
if (ll == NULL)
ll = file->line_list;
else
ll = ll->next;
set_prompt( block22b, prompt_line );
insertion_sort_block( file->block_br, file->block_er, ll );
/*
* housekeeping. mark the file as dirty and restore the
* cursors, which are scrambled during the sort.
*/
file->dirty = GLOBAL;
restore_cursors( file );
restore_screen_line( 0, prompt_line, line_buff );
}
} else {
/*
* can only sort box blocks
*/
error( WARNING, prompt_line, block23 );
rc = ERROR;
}
} else {
/*
* box not marked
*/
error( WARNING, prompt_line, block24 );
rc = ERROR;
}
return( rc );
}
/*
* Name: quick_sort_block
* Purpose: sort lines according to text in marked BOX block
* Date: Jaunary 10, 1993
* Passed: low: starting line in box block
* high: ending line in a box block
* low_node: starting node in box block
* high_node: ending node in box block
* Notes: Quicksort lines in the BOX block according to keys in
* a box block.
* because the median of three method is used to find the partion
* node, high - low should be greater than or equal to 2.
* with end recursion removal and sorting the smallest sublist
* first, our stack only needs room for log2 (N+1)/(M+2) nodes.
* a stack size of 24 can reliably handle almost 500 million lines.
*/
void quick_sort_block( long low, long high, line_list_ptr low_node,
line_list_ptr high_node )
{
long low_rline_stack[24];
long high_rline_stack[24];
line_list_ptr low_node_stack[24];
line_list_ptr high_node_stack[24];
long low_count;
long high_count;
long count;
line_list_ptr low_start;
line_list_ptr low_head;
line_list_ptr low_tail;
line_list_ptr high_end;
line_list_ptr high_head;
line_list_ptr high_tail;
line_list_ptr equal_head;
line_li