📜  Java中的三向基数快速排序

📅  最后修改于: 2022-05-13 01:55:21.443000             🧑  作者: Mango

Java中的三向基数快速排序

基本上,顾名思义,3-Way Radix Quicksort 是 radix 和 3-way quicksort 的组合。它是一种介于基数和三向快速排序之间的混合排序。该算法主要用于对字符串进行排序。

基数排序背后的主要思想是使用所有整数的数字(从 LSD 到 MSD)来执行散列并将它们划分为单独的列表并进行连接。同样,我们将使用字符串的 MSD字符,然后使用这些字符继续执行所谓的三向快速排序。

三路快速排序基本上只是一般快速排序的一种情况。这个想法是,如果我们使用快速排序,那么可能会有一种情况,我们会在字符数组中得到相同的字符(这里我们使用基数排序思想对字符串进行排序,将所有字符一一排序)。

因此,为了处理这种情况,我们将数组分为三部分:

  1. 分区包含的字符少于主元字符。
  2. 字符的分区等于主元字符的分区。
  3. 最后一个分区包含大于主元字符的字符。

所以基本上会发生的是:

  1. 我们会考虑每个字符串的 MSD字符(基数排序的想法)。
  2. 然后我们将对这个字符数组执行快速排序,这将导致数组分成 3 部分(如上所述)。

这种划分如下图所示。

3-Way-Radix-Quicksort-in-Java

图片说明:

获得分区后,我们可以看到,在第二个分区中,我们无法对字符串的第一个字符递归执行快速排序,因为在该分区中,所有字符串都具有相同的第一个字符(在此示例中为 's') .所以我们将根据下一个字符进行分区。对于另外两个,我们将从第一个字符开始再次回忆相同的排序。这就是关于三向快速排序的全部想法。

这里要注意的主要事情是所有字符串的长度都不相同,因此在某些步骤中,我们可以有一个条件,即不再有主字符串的字符,而其他字符串有字符,因此交换和比较字符在这种情况下是不可能的。

因此,为了处理这种情况,我们首先要找到数组中字符串的最大长度,然后在每个字符串后面附加一个字符值小于字母表的字符。

递归地执行上述算法将生成一个已排序的数组,因此我们将能够对字符串数组进行排序。

递归实现:

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