Java中的三向基数快速排序
基本上,顾名思义,3-Way Radix Quicksort 是 radix 和 3-way quicksort 的组合。它是一种介于基数和三向快速排序之间的混合排序。该算法主要用于对字符串进行排序。
基数排序背后的主要思想是使用所有整数的数字(从 LSD 到 MSD)来执行散列并将它们划分为单独的列表并进行连接。同样,我们将使用字符串的 MSD字符,然后使用这些字符继续执行所谓的三向快速排序。
三路快速排序基本上只是一般快速排序的一种情况。这个想法是,如果我们使用快速排序,那么可能会有一种情况,我们会在字符数组中得到相同的字符(这里我们使用基数排序思想对字符串进行排序,将所有字符一一排序)。
因此,为了处理这种情况,我们将数组分为三部分:
- 分区包含的字符少于主元字符。
- 字符的分区等于主元字符的分区。
- 最后一个分区包含大于主元字符的字符。
所以基本上会发生的是:
- 我们会考虑每个字符串的 MSD字符(基数排序的想法)。
- 然后我们将对这个字符数组执行快速排序,这将导致数组分成 3 部分(如上所述)。
这种划分如下图所示。
图片说明:
- So basically as shown that there are 11 strings in the array, and we have to sort them. So now considering the first character of all strings gives an array of {s,a,h,s,s,z,b,t,c,u,s}. This is the idea got from radix sort. Now we are to sort this array of characters on the basis of the idea of quick sort.
- So here the pivot element we are considering is first element of array i.e. ‘s’. Now we are using quicksort to make partition. Partitions are done on the basis that :
- First we are considering the first character as the pivot and also we have to pointers ‘i’ and ‘j’. Pointer ‘i’ moves form start to end and ‘j’ moves from end to start. Initially i=1 and j =n-1; this would help us to get the two boundary index of the second partition.
- Ranges of partition than would be 1st one form 0 – i , 2nd form i+1 – j-1 and third form j to n-1;
- if arr[i]
- if arr[i]==pivot it is remained there only, and the pointer is incremented to next one.
- if arr[i]>pivot, the string at j is swapped with arr[i] string and j is decremented.
So after performing these operations we will get the three partitioned array as shown.
获得分区后,我们可以看到,在第二个分区中,我们无法对字符串的第一个字符递归执行快速排序,因为在该分区中,所有字符串都具有相同的第一个字符(在此示例中为 's') .所以我们将根据下一个字符进行分区。对于另外两个,我们将从第一个字符开始再次回忆相同的排序。这就是关于三向快速排序的全部想法。
这里要注意的主要事情是所有字符串的长度都不相同,因此在某些步骤中,我们可以有一个条件,即不再有主字符串的字符,而其他字符串有字符,因此交换和比较字符在这种情况下是不可能的。
因此,为了处理这种情况,我们首先要找到数组中字符串的最大长度,然后在每个字符串后面附加一个字符值小于字母表的字符。
Why smaller?
consider an example:
Array is a={hero, heroes, her}
Here if we give each string with fewer characters than the max amount needed(i.e. 6) a character which is greater than alphabets (say ‘~’), then a will become a={hero~~, heroes, her~~~}.
sorting this array would give the result as {heroes, hero~~, her~~~} but the real answer should be {her, hero, heroes}.
递归地执行上述算法将生成一个已排序的数组,因此我们将能够对字符串数组进行排序。
递归实现:
Java
// Java program for 3-Way Radix Quicksort
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public class GFG {
// swapping method.
public static void swp(String[] s, int x, int y)
{
String tmp = s[x];
s[x] = s[y];
s[y] = tmp;
}
// sort method.
public static void srt(String[] s, int start, int last,
int character_index)
{
// base condition if no further index possible.
if (start >= last)
return;
// first making a start pointer for dividing the
// list from start to start_pointer.
int start_pointer = start;
// last_pointer and last are the boundaries for the
// third list.
int last_pointer = last;
// taking the ascii value of the pivot at the index
// given.
int char_ascii_value_pivot
= s[start].charAt(character_index);
int pointer = start + 1;
// starting a pointer to scan the whole array to
// sort.
while (pointer <= last) {
// ASCII value of char at the position of all
// the strings to compare with that of the pivot
// char.
int char_ascii_value_element
= s[pointer].charAt(character_index);
// if the element has char less than pivot than
// swapping it with the top element and
// incrementing the top boundary of the first
// list.
if (char_ascii_value_pivot
> char_ascii_value_element) {
swp(s, start_pointer, pointer);
start_pointer++;
// incrementing the pointer to check for
// next string.
pointer++;
}
else
// if found larger character than it is
// replaced by the element at last_pointer
// and lower boundary is raised by
// decrementing it.
if (char_ascii_value_pivot
< char_ascii_value_element) {
swp(s, last_pointer, pointer);
last_pointer--;
pointer++;
}
// if character is the same as that of the pivot
// then no need to swap and move the pointer on
else {
pointer++;
}
}
// now performing same sort on the first list
// bounded by start and start_pointer with same
// character_index
srt(s, start, start_pointer - 1, character_index);
// if we have more character left in the pivot
// element than recll quicksort on the second list
// bounded by start_pointer and last_pointer and
// next character_index.
if (char_ascii_value_pivot >= 0)
srt(s, start_pointer, last_pointer,
character_index + 1);
// lastly the third list with boundaries as
// last_pointer and last.
srt(s, last_pointer + 1, last, character_index);
}
public static void main(String[] args) throws Exception
{
// predefined array of five element all of same
// length.
String s[]
= { "some", "same", "hero", "make", "zero" };
// calling sort function to sort the array using
// 3-way-radix-quicksort.
srt(s, 0, 4, 0);
// printing the sorted array;
// here w are calling function by passing parameters
// using references .
for (int i = 0; i < 5; ++i)
System.out.println(s[i]);
}
}
Java
// Java program for 3-Way radix QuickSort
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public class GFG {
// swapping method.
public static void swp(String[] s, int x, int y)
{
String tmp = s[x];
s[x] = s[y];
s[y] = tmp;
}
// sort method.
public static void srt(String[] s, int start, int last,
int character_index)
{
// base condition if no further index possible.
if (start >= last)
return;
// first making a start pointer for dividing the
// list from start to start_pointer.
int start_pointer = start;
// last_pointer and last are the boundaries for the
// third list.
int last_pointer = last;
// taking the ASCII value of the pivot at the index
// given.
int char_ascii_value_pivot = s[start].charAt(character_index);
int pointer = start + 1;
// starting a pointer to scan the whole array to
// sort.
while (pointer <= last)
{
// ASCII value of char at the position of all
// the strings to compare with that of the pivot
// char.
int char_ascii_value_element = s[pointer].charAt(character_index);
// if the element has char less than pivot than
// swapping it with the top element and
// incrementing the top boundary of the first
// list.
if (char_ascii_value_pivot> char_ascii_value_element)
{
swp(s, start_pointer, pointer);
start_pointer++;
// incrementing the pointer to check for
// next string.
pointer++;
}
else
// if found larger character than it is
// replaced by the element at last_pointer
// and lower boundary is raised by
// decrementing it.
if (char_ascii_value_pivot< char_ascii_value_element)
{
swp(s, last_pointer, pointer);
last_pointer--;
pointer++;
}
// if character is same as that of the pivot then
// no need to swap and move the pointer on
else
{
pointer++;
}
}
// now performing same sort on the first list
// bounded by start and start_pointer with same
// character_index
srt(s, start, start_pointer - 1, character_index);
// if we have more character left in the pivot
// element than recll quicksort on the second list
// bounded by start_pointer and last_pointer and
// next character_index.
if (char_ascii_value_pivot >= 0)
srt(s, start_pointer, last_pointer,character_index + 1);
// lastly the third list with boundaries as
// last_pointer and last.
srt(s, last_pointer + 1, last, character_index);
}
public static void main(String[] args) throws Exception
{
// predefined array of five element all of different
// length.
String s[] = { "sam", "same", "her", "make", "zebra" };
int max_character_index = 0;
// finding max_character_index
for (int i = 0; i < 5; ++i)
if (s[i].length() > max_character_index)
max_character_index = s[i].length();
// adding each string with a character having less
// ascii value than alphabets.
for (int i = 0; i < 5; ++i)
if (s[i].length() < max_character_index)
while (s[i].length() < max_character_index)
s[i] += '?';
// calling sort function to sort the array using
// 3-way-radix-quicksort.
srt(s, 0, 4, 0);
// printing the sorted array;
// here we are calling function by passing
// parameters using references . printing without the
// appended character.
for (int i = 0; i < 5; ++i)
{
String ans = "";
for (int j = 0; j < s[i].length(); ++j)
if (s[i].charAt(j) != '?')
ans += s[i].charAt(j);
else
break;
System.out.println(ans);
}
}
}
hero
make
same
some
zero
示例 2:对不同长度的字符串进行排序。
Java
// Java program for 3-Way radix QuickSort
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public class GFG {
// swapping method.
public static void swp(String[] s, int x, int y)
{
String tmp = s[x];
s[x] = s[y];
s[y] = tmp;
}
// sort method.
public static void srt(String[] s, int start, int last,
int character_index)
{
// base condition if no further index possible.
if (start >= last)
return;
// first making a start pointer for dividing the
// list from start to start_pointer.
int start_pointer = start;
// last_pointer and last are the boundaries for the
// third list.
int last_pointer = last;
// taking the ASCII value of the pivot at the index
// given.
int char_ascii_value_pivot = s[start].charAt(character_index);
int pointer = start + 1;
// starting a pointer to scan the whole array to
// sort.
while (pointer <= last)
{
// ASCII value of char at the position of all
// the strings to compare with that of the pivot
// char.
int char_ascii_value_element = s[pointer].charAt(character_index);
// if the element has char less than pivot than
// swapping it with the top element and
// incrementing the top boundary of the first
// list.
if (char_ascii_value_pivot> char_ascii_value_element)
{
swp(s, start_pointer, pointer);
start_pointer++;
// incrementing the pointer to check for
// next string.
pointer++;
}
else
// if found larger character than it is
// replaced by the element at last_pointer
// and lower boundary is raised by
// decrementing it.
if (char_ascii_value_pivot< char_ascii_value_element)
{
swp(s, last_pointer, pointer);
last_pointer--;
pointer++;
}
// if character is same as that of the pivot then
// no need to swap and move the pointer on
else
{
pointer++;
}
}
// now performing same sort on the first list
// bounded by start and start_pointer with same
// character_index
srt(s, start, start_pointer - 1, character_index);
// if we have more character left in the pivot
// element than recll quicksort on the second list
// bounded by start_pointer and last_pointer and
// next character_index.
if (char_ascii_value_pivot >= 0)
srt(s, start_pointer, last_pointer,character_index + 1);
// lastly the third list with boundaries as
// last_pointer and last.
srt(s, last_pointer + 1, last, character_index);
}
public static void main(String[] args) throws Exception
{
// predefined array of five element all of different
// length.
String s[] = { "sam", "same", "her", "make", "zebra" };
int max_character_index = 0;
// finding max_character_index
for (int i = 0; i < 5; ++i)
if (s[i].length() > max_character_index)
max_character_index = s[i].length();
// adding each string with a character having less
// ascii value than alphabets.
for (int i = 0; i < 5; ++i)
if (s[i].length() < max_character_index)
while (s[i].length() < max_character_index)
s[i] += '?';
// calling sort function to sort the array using
// 3-way-radix-quicksort.
srt(s, 0, 4, 0);
// printing the sorted array;
// here we are calling function by passing
// parameters using references . printing without the
// appended character.
for (int i = 0; i < 5; ++i)
{
String ans = "";
for (int j = 0; j < s[i].length(); ++j)
if (s[i].charAt(j) != '?')
ans += s[i].charAt(j);
else
break;
System.out.println(ans);
}
}
}
her
make
sam
same
zebra