日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Perl Sort

發布時間:2023/12/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Perl Sort 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://www.sysarch.com/Perl/sort_paper.html


A Fresh Look at Efficient Perl Sorting

Uri Guttman and Larry Rosler

Uri Guttman is an independent Perl and Internet consultant; uri@sysarch.com
Larry Rosler is at Hewlett-Packard Laboratories, Palo Alto, CA; lr@hpl.hp.com

Abstract

Sorting can be a major bottleneck in Perl programs. Performancecan vary by orders of magnitude, depending on how the sort iswritten. In this paper, we examine Perl′s sort function indepth and describe how to use it with simple and complex data. Next weanalyze and compare several well-known Perl sorting optimizations(including the Orcish Maneuver and the Schwartzian Transform). We thenshow how to improve their performance significantly, by packing multiplesortkeys into a single string. Finally, we present a fresh approach,using the sort function with packed sortkeys and without asortsub. This provides much better performance than any of the othermethods, and is easy to implement directly or by using a new module wecreated, Sort::Records.

NOTE: Sort::Records died during development but five years later,Sort::Maker was released and does all that was promised and more. Findit on CPAN

What is sorting and why do we use it?

Sorting is the rearrangement of a list into an order defined by a monotonically increasing or decreasing sequence of sortkeys, where each sortkey is a single-valued function of the corresponding element of the list. (We will use the term sortkeys to avoid confusion with the keys of a hash.)

Sorting is used to reorder a list into a sequence suitable for further processing or searching. In many cases the sorted output is intended for people to read; sorting makes it much easier to understand the data and to find a desired datum.

Sorting is used in many types of programs and on all kinds of data. It is such a common, resource-consuming operation that sorting algorithms and the creation of optimal implementations comprise an important branch of computer science.

This paper is about creating optimal sorts using Perl. We start with a brief overview of sorting, including basic algorithm theory and notation, some well-known sorting algorithms and their efficiencies, sortkey processing, and sorting outside of Perl. Next we will describe Perl′s sort function [1] and basic ways to use it. Then we cover handling complex sortkeys, which raises the question of how to optimize their processing. Finally we introduce a relatively new method, which moves all the sortkey processing out of the sort function, and which produces the most efficient Perl sort. A new module is also described, which implements this sorting technique and which has powerful support for sortkey extraction (the processing of the input data to produce the sortkeys.

Algorithm and sorting theory

A complete discussion of algorithm and sorting theory is beyond the scope of this paper. This section will cover just enough theory and terminology to explain the methods that we use to compare sort techniques.

The complexity of an algorithm is a measure of the resources needed to execute the algorithm -- typically there is a critical operation that needs to be executed many times. Part of algorithm theory is figuring out which operation is the limiting factor, and then formulating a function that describes the number of times the operation is executed. This complexity function is commonly written with the big-O notation -- O(f(N)) -- where `O′ is read as `order of′ and `f(N)′ is some function of N, the size of the input data set.

O(f(N)) comparisons have some unusual properties. The actual size of N is usually irrelevant to the correct execution of an algorithm, but its influence on the behavior of f(N) is critical. If an algorithm′s order is O(N*logN + N), when N is large enough the effect of the N on the function′s value is negligible compared to the N*logN expression. So that algorithm′s order is just O(N*logN). In many cases the calculated order function for an algorithm is a polynomial of N, but you see only the term with the highest power, and no coefficient is shown. Similarly, if two algorithms have the same order but one does more work for each operation, they are still equivalent in order space, even though there may be a substantial difference in real-world speeds. That last point is crucial in the techniques we will show to optimize Perl sorts, all of which have the same big-O function, O(N*logN).

Here are some well-known algorithms and their order functions (adapted from [2]):

Notation

Name

Example

O(1)

constant

array or hash index

O(logN)

logarithmic

binary search

O(N)

linear

string comparison

O(N*logN)

n log n

advanced sort

O(N**2)

quadratic

simple sort

O(N**3)

cubic

matrix multiplication

O(2**N)

exponential

set partitioning

Sorting′s critical operation is determining in which order to put pairs of elements of the data. The comparison can be as simple as finding whether two numbers are equal or which is greater than the other (or doing similar operations on strings), or it can be quite complex.

Simple sorting algorithms (bubble or insertion sorts) compare each element to each of the others repeatedly, so their complexity is O(N**N). Even with the triangle optimization ($x is equal to $x, and $x compared to $y is the negative of $y compared to $x), which reduces the function to O((N * (N-1))/2), the complexity is still O(N**N), as explained above.

But these algorithms have their uses. When N is very small, they can actually be faster than the other methods, because the O(1) and O(N) overhead of the advanced sorts may outweigh the O(N**2) behavior of the simple sorts. "Fancy algorithms are slow when N is small, and N is usually small. Fancy algorithms have big constants." [3] The really important cases, which are worth care in the coding, occur when N is large.

Advanced sorting methods repeatedly partition the records to be sorted into smaller sets, to reduce the total number of comparisons needed. Their complexity is O(N*logN), which can be much less than O(N**2) for sufficiently large values of N. These algorithms include `tree sort′, `shell sort′, and `quicksort′. [4]

Some specialized sort algorithms (such as `radix sort′) work by comparing pieces of numeric sortkeys, and can achieve linear complexity (O(N)) [5]. These methods are not general-purpose, so we will not address them further.

One property of sort algorithms is whether they are stable. A stable sort preserves the order in the sorted data of two elements that compare equal. Some sorting problems require stability. The simple sorting algorithms are generally stable; the advanced ones are not. We will show how to make Perl′s advanced sort behave stably if required.

An important sorting variation is when the original data elements can′t conveniently be moved around by the sort algorithm′s shuffling. So instead of sorting the elements directly, you sort their index numbers. You then use the sorted indexes to create a list of sorted elements. Some sort operators in other languages (APL comes to mind) simply return sorted indexes, and it is up to the programmer to use them correctly. We will show how to create an efficient Perl index sort and where it is useful.

Sortkeys

If you are sorting a set of scalar-valued elements where the comparison looks at the entire element, the sortkey is simply the entire element. More generally, the sortkey is based on some properties that are functions of all or part of the element. Such subkeys may be extracted from internal properties of parts of the element (fields) or derived from external properties of the element (such as the modification date of a file named by the element, which is quite expensive to retrieve from the file system).

To avoid repeated computation of the sortkeys, the sort process has to retain the association between records and their extracted or derived sortkeys. Sorting theory and algorithms usually ignore the cost of this association, as it is typically a constant factor of the comparison operation. But as we will see later, in the real world, removing that overhead or reducing it from O(N*logN) to O(N) is very valuable, especially as N grows.

Complex sortkeys can add tremendously to the overhead of each comparison. This occurs where the records have to be sorted by primary, secondary, and lower-order subkeys. This is also known as doing a subsort on the lower keys. Extracting and comparing complex sortkeys can be costly and error-prone.

No general-purpose implementation of a sort algorithm can efficiently support extracting and comparing different types of sortkeys. Therefore, most sort implementations provide a simple interface to call a sortsub -- a custom comparison subroutine which is passed two operands. These operands can be the records themselves, or references to or indexes of complex records. The comparison returns a negative, zero, or positive value, depending on the ordering of the sortkeys of the two records. The programmer is responsible for any preprocessing of the records to generate the sortkeys and any postprocessing to retrieve the sorted data. The generic sort function only manages the comparisons and shuffles the operands into sorted order.

As Perl′s sort function is O(N*logN), efficiency must come from extracting and comparing the sortkeys using the least amount of work. Much of this paper will be about methods to make sortkey extraction and comparison as efficient as possible.

External sorting

Every popular commercial operating system offers a sort utility. Unix/POSIX flavors typically have a sort command which is fast and fairly flexible with regard to sortkey extraction from text files. In some cases, the Unix/POSIX sort command may be easier to code and more efficient than using the Perl sort function.

Several vendors sell highly optimized commercial sort packages that have received decades of attention and can handle massive amounts of data. But they are very expensive and not suitable for use inside a Perl program.

All of these are capable of dealing efficiently with very large amounts of data, using external media such as disk or tape files for intermediate storage when needed. In contrast, the Perl sort function requires that the entire list of operands be in (real or -- much more expensively -- virtual) memory at the same time. So Perl is not the appropriate tool to use for huge sorts (where huge is defined by your system′s memory limits), which we shall not consider further.

Internal sorting

The Perl sort function uses an implementation of the quicksort algorithm that is similar to (but more robust than) the qsort function in the ANSI/ISO Standard C Library [6]. In the simplest use, the Perl sort function requires no sortsub:

@out = sort @in;

This default sorts the data in ascending lexicographic order, using the fast C memcmp function as the comparison operation. If a locale is specified, it substitutes the more complicated and somewhat slower C strcoll function.

If you want any kind of ordering other than this, you must provide a custom comparison sortsub. The sortsub can be specified either as a code block, the name of a subroutine, or a typeglob that refers to a subroutine (a coderef). In Perl 5.6, a scalar variable that contains a coderef can also be used to specify the sortsub.

In order to optimize the calling of the sortsub, Perl bypasses the usual passing of arguments via @_, using instead a more efficient special-purpose method. Within the sortsub, the special global package variables $a and $b are aliases for the two operands being compared. The sortsub must return a number less than 0, equal to 0, or greater than 0, depending on the result of comparing the sortkeys of $a and $b. The special variables $a and $b should never be used to change the values of any input data, as this may break the sort algorithm.

Even the simplest custom sort in Perl will be less efficient than using the default comparison. The default sort runs entirely in C code in the perl core, but any sortsub must execute Perl code. A well-known optimization is to minimize the amount of Perl code executing and to try to stay inside the perl core as much as possible. Later we will see various optimization techniques that will reduce the amount of Perl code executed.

The primary goal of this paper is to perform all sorts using the default comparison. Here is how an explicit ascending lexicographic would be done using a sortsub:

@out = sort { $a cmp $b } @in;

For a simple measurement, compare Default and Explicit in Benchmark A1 of Appendix A. The default method is about twice as fast as the explicit method.

Trivial sorts

We call trivial sorts those that use the entire record as the sortkey and do only a minimal amount of processing of the record. To do trivial Perl sorts other than ascending lexicographic, you just need to create an appropriate sortsub. Here are some common ones that perform useful functions.

The simplest such example is the ascending numeric sort, which uses the picturesquely monikered `spaceship′ operator:

@out = sort { $a <=> $b } @in;

A numeric sort capability is required because the lexicographic order of, say, (1, 2, 10) does not correspond to the numeric order.

If you want the sort to be in descending order there are three techniques you can use. The worst is to negate the result of the comparison in the sortsub. Better is to reverse the order of the comparison by swapping $a and $b. This has the same speed as the corresponding forward sort.

# descending numeric@out = sort { $b <=> $a } @in; # descending lexicographic@out = sort { $b cmp $a } @in;

The best method is to apply the reverse function to the result of a default ascending lexicographic sort.

@out = reverse sort @in;

Note that this is faster than using the explicit descending lexicographic sort, for the reason discussed above: the default sort is faster than using a sortsub. The reverse function is efficient because it just moves pointers around.

Another common problem is sorting with case insensitivity. This is easily solved using the lc or uc function. Either one will give the same results.

@out = sort { lc $a cmp lc $b } @in;

Benchmark A1 analyzes these examples as a function of the input size. The O(N*logN) behavior is apparent, as well as the cost of using even a simple built-in function like lc in the sortsub.

Fielded and record sorts

The above trivial sorts sort the input list using as the sortkey the entire string (for a lexicographic sort) or the first number in each datum (for a numeric sort). More typically, the sortkey is based on some property that is a function of all or part of each datum. Several individual subkeys may be combined into a single sortkey or may be compared in pairs individually.

A complex string may be divided into fields, some of which may serve as subkeys. For example, the Unix/POSIX sort command provides built-in support for collation based on one or more fields of the input; the Perl sort function does not, and the programmer must provide it. One CPAN module focuses on fielded sorts [7].

If your data are records which are complex strings or references to arrays or hashes, you have to perform comparisons on selected parts of the records. This is called record sorting. (Fielded sorts are a subset of record sorts.)

In the code examples that follow, KEY() is meant to be substituted with some Perl code that performs sortkey extraction. It is best that it not be an actual subroutine call, because subroutine calls within sortsubs can be expensive. Calls to built-in Perl functions (such as the calls to lc in the example above) are like Perl operators, thus relatively less expensive.

When sorting string records, $a and $b are set to those strings, so to extract the sortkeys you generally perform various string operations on the records. Functions commonly used for this include split, substr, unpack, and m//. Here is one example, sorting a list of password-file lines by user name using split. The fields are separated by colons, and the user name is the first field.

@out = sort {(split ':', $a, 2)[0] cmp(split ':', $b, 2)[0]} @pw_lines;

Multi-subkey sorts

In some cases you need to sort records by a primary subkey, then for all the records with the same primary subkey value, you need to sort by a secondary subkey. One horribly inefficient way to do this is to sort first by the primary subkey, then get all the records with a given subkey and sort them by the secondary subkey. The standard method is to do a multi-key sort. This entails extracting a subkey for each field, and comparing paired subkeys in priority order. So if two records with the same primary subkey are compared, they will actually be compared based on the secondary subkey. Sorting on more than two subkeys is done by extending the logic.

Perl has a very nice feature which makes multi-key sorts easy to write. The || (short-circuit or) operator returns the actual value of the first logically true operand it sees. So if you use || to concatenate a set of key comparisons, the first comparison is the primary subkey. If a pair of primary subkeys compare equal, the sortsub′s return value will be the result of the secondary subkey comparison.

An example will illustrate this `ladder′ of comparisons better than more text. Here is a three-subkey sort:

@out = sort {# primary subkeys comparisonKEY1($a) cmp KEY1($b)||# or if they are equal# return secondary comparison# descending numeric comparisonKEY2($b) <=> KEY2($a)||# or if they are equal# return tertiary comparison# lexicographic comparisonKEY3($a) cmp KEY3($b)} @in;

Naive multi-subkey record sorts

In the two previous examples, we showed a sort with relatively expensive sortkey extraction (via split), and a multi-subkey sort. Let′s combine them. For concreteness, we shall deal with a problem that has received much attention in comp.lang.perl.misc -- sorting a list of IP addresses in `dotted-quad′ form. Each element of the list is a string of the form "nnn.nnn.nnn.nnn\tabc.xyz.com\n", where nnn represents a decimal integer between 0 and 255, with or without leading zero-padding.

In the most naive approach, we sort on each of these four numeric fields as individual subkeys, in succession.

@out = sort {my @a = $a =~/(\d+)\.(\d+)\.(\d+)\.(\d+)/;my @b = $b =~/(\d+)\.(\d+)\.(\d+)\.(\d+)/;$a[0] <=> $b[0] ||$a[1] <=> $b[1] ||$a[2] <=> $b[2] ||$a[3] <=> $b[3]} @in;

Even for small lists this is very slow, because of the many Perl operations executed in the sortsub for every one of the O(N*logN) comparisons.

Computing a single packed-string sortkey

To improve performance, we will derive from these four subkeys a single packed-string sortkey for each IP address, which we can then use to sort the array monotonically increasing.

The following expression produces the shortest key, a string of four bytes, with the least Perl calculation:

pack 'C4' => $string =~/(\d+)\.(\d+)\.(\d+)\.(\d+)/

This uses the fancy comma operator, =>, which you can read as `applied to′. We then sort these sortkeys lexicographically.

The following, then, is the next approach toward achieving an efficient sort:

@out = sort {pack('C4' => $a =~/(\d+)\.(\d+)\.(\d+)\.(\d+)/)cmppack('C4' => $b =~/(\d+)\.(\d+)\.(\d+)\.(\d+)/)} @in;

Benchmark A2 shows that comparing the subkeys in pairs is less efficient than packing them and comparing the packed strings. This observation applies to all sorting methods. In further benchmarks of advanced sorts for this problem, we will always used packed sortkeys.

Nevertheless, naive sorting is still woefully inefficient, because both sortkeys are recomputed every time one input operand is compared against another. What we need now is a way to compute each sortkey once only and to remember the result.

Advanced sorts

As all sorts in Perl use the builtin sort function and therefore the same quicksort algorithm, all Perl sorts are of order O(N*logN). We can′t improve upon that, so we have to address other issues to gain efficiency. As the complexity is fixed, tackling the constant factors can be fruitful and, in the real world, can produce significant improvements in efficiency. When a sortsub needs to generate a complex sortkey, that is normally done O(N*LogN) times, but there are only N records, hence N sortkeys. What if we were to extract the sortkey only once per record, and keep track of which sortkey belonged to which record?

Caching the sortkeys

The obvious way to associate sortkeys with the records from which they were created is to use a hash. The hash can be created in a preprocessing pass over the data. If the approximate size of the data set is known, preallocating the hash improves performance.

keys my %cache = @in;$cache{$_} = KEY($_) for @in;

The following sets up the cache more efficiently, using a hash slice:

keys my %cache = @in;@cache{@in} = map KEY($_) => @in;

Then the sortsub simply sorts by the values of the cached sortkeys.

@out = sort {$cache{$a} cmp $cache{$b)} @in;

In essence, we have replaced lengthy computations in the sortsub by speedy (O(1)) hash lookups.

If you want to do a complex multi-key comparison, you either have to use a separate cache for each subkey or combine subkeys in a similar way to the packed-sort optimizations we will describe later. Here is an example of the former:

keys my %cache1 = @in;keys my %cache2 = @in;($cache1{$_}, $cache2{$_}) =map { KEY1($_), KEY2($_) } $_for @in;@out = sort {$cache1{$a} cmp $cache1{$b) ||$cache2{$b} <=> $cache2{$a} }@in;

Alternatively, a multi-level cache can be used, which sacrifices speed to save some space:

keys my %cache = @in;$cache{@in} =map [ KEY0($_), KEY1($_) ]=> @in;@out = sort {$cache{$a}[0] cmp $cache{$b)[0]||$cache{$b}[1] <=> $cache{$a}[1]} @in;

An important point about cached sorts is that no postprocessing is needed to retrieve the sorted records. The method sorts the actual records, but uses the cache to reduce the sortkey extraction to O(N).

The Orcish Maneuver (OM)

The Orcish Maneuver (invented by Joseph N. Hall [8]) eliminates the preprocessing pass over the data, which might save keeping a copy of the data if they are being read directly from a file. It does the sortkey extraction only once per record, as it checks the hash to see if it was done before. The test and storage of the sortkey is done with the ||= operator (short-circuit or-assignment), which will evaluate and assign the expression on the right to the lvalue on the left, if the lvalue is false. The name `orcish′ is a pun on `or-cache′. The full statement in the sortsub looks like this:

keys my %or_cache = @in;@out = sort {($or_cache{$a} ||= KEY($a))cmp($or_cache{$b} ||= KEY($b))} @in;

That sees if the sortkey for $a is cached, and if not, extracts it and caches it. The sortkey for $a is then compared to the sortkey for $b (which is found in the same way).

Here is an example of a two-subkey comparison using two caches:

keys my %or_cache1 = @in;keys my %or_cache2 = @in;@out = sort {($or_cache1{$a} ||= KEY1($a))cmp($or_cache1{$b} ||= KEY1($b))||($or_cache2{$b} ||= KEY2($b))<=>($or_cache2{$a} ||= KEY2($a))} @in;

The OM has some minor efficiency flaws. An extra test is necessary after each sortkey is retrieved from the or-cache. Furthermore, if an extracted sortkey has a false value, it will be recomputed every time. This usually works out all right, because the extracted sortkeys are seldom false. However, except when the need to avoid reading the data twice is critical, the explicit cached sort is always slightly faster than the OM. (See Benchmark A3.)

The Schwartzian Transform (ST)

A more efficient approach to caching sortkeys, without using named temporary variables, was popularized by Randal L. Schwartz, and dubbed the Schwartzian Transform [9, 10]. (It should really be called the Schwartz Transform, after the model of the Fourier and Laplace Transforms, but it is too late to fix the name now.)

The significant invention in the ST is the use of anonymous arrays to store the records and their sortkeys. The sortkeys are extracted once, during a preprocessing pass over all the data in the list to be sorted (just as we did before in computing the cache of sortkeys).

@out =map $_->[0] =>sort { $a->[1] cmp $b->[1] }map [ $_, KEY($_) ] =>@in;

The ST doesn′t sort the actual input data. It sorts the references to anonymous arrays that contain the original records and the sortkeys. So we have to postprocess to retrieve the sorted records from the anonymous arrays.

Using the ST for a multi-subkey sort is straightforward. Just store each successive extracted subkey in the next entry in the anonymous array. In the sortsub, do an or between comparisons of successive subkeys, as with the OM and the naive sorts.

@out =map $_->[0] =>sort { $a->[1] cmp $b->[1] ||$b->[2] <=> $a->[2] }map [ $_, KEY1($_), KEY2($_) ]=> @in;

For a very illuminating deconstruction and reconstruction of the ST, see [11].

The packed-default sort

Each of the advanced sorting techniques described above saves the operands to be sorted together with their sortkeys. (In the cached sorts, the operands are the keys of a hash and the sortkeys are the values of the hash; in the Schwartzian Transform, the operands are the first elements of anonymous arrays, the sortkeys are the other elements of the arrays.) We now extend that idea to saving the operands to be sorted together with packed-string sortkeys, using concatenation.

This little-known optimization improves on the ST by eliminating the sortsub itself, relying on the default lexicographic sort, which as we showed earlier is very efficient. This is the method used in the new Sort::Maker module.

To accomplish this goal, we modify the ST by replacing its anonymous arrays by packed strings. First we pack into a single string each subkey followed last by the operand to be sorted. Then we sort lexicographically on those strings, and finally we retrieve the operands from the end of the strings.

@out =map substr($_, 4) =>sortmap pack('C4' =>/(\d+)\.(\d+)\.(\d+)\.(\d+)/). $_ => @in;

Several methods can be used, singly or in combination, to construct the packed strings, including concatenation, pack, or sprintf. Several methods can be used to retrieve the operands, including substr (shown here), which is likely to be the fastest, split, unpack or a regex.

Multiple subkeys are simply concatenated, suitably delimited if necessary. Techniques for computing subkeys of various types are presented in Appendix B.

Benchmarks of the packed-default sort

Benchmark A4 compares the two most advanced general-purpose sorting techniques, ST and packed-default. These multi-stage sorts are measured both as individual stages with saved intermediate data and as single statements.

The packed-default sort is about twice as fast as the ST, which is the fastest familiar Perl sorting algorithm.

Earlier, we showed a trivial sort using the lc function. Even for that case, the packed-default sort provides better performance when more than a few data items are being sorted. See Benchmark A5, which shows quasi-O(N) behavior for the packed-default sort (because the sorting time is small relative to the sortkey extraction).

Sorting a list of arrays or hashes

Consider the common problem of sorting a two-dimensional data structure, a list of references to arrays or to hashes, where the sortkeys are functions of the values of the submembers.

If we were to use the packed-default method, the references would be converted to strings and appended to the sortkeys. After sorting, the operands could be retrieved as strings, but would no longer be usable as references. Instead, we must use the indexes of the list members as the operands to be sorted.

The following benchmark compares a packed-sortkey ST sort with an indexed sort that uses the packed-default approach. The list being sorted comprises references to arrays, each of which has two elements: an IP address (which serves as the primary sortkey), and a domain name (which serves as the secondary sortkey). These are the same data as used in the above benchmarks, split into two array elements.

@out =map $_->[0] =>sort { $a->[1] cmp $b->[1] }map [ $_, pack('C4 A*' =>$_->[0] =~/(\d+)\.(\d+)\.(\d+)\.(\d+)/,$_->[1]) ] => @in;my $i = 0;keys my %h = @in;@h{ map pack('C4 A* x N' => $_->[0]=~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/,$_->[1], $i++) => @in } = @in;@out = @h{ sort keys %h };

The indexed sort is faster than the ST once again. (See Benchmark A6.)

Indexed sorts and stable sorts

In the indexed sort, the auto-incrementing index $i ensures that no array records will have identical packed sortkeys. It also ensures that the sort will be stable.

Any Perl sort can be stabilized by using such an index as the final tie-breaking subkey. For an indexed sort, the index is actually the operand being sorted. This fact offers another possible performance advantage for the indexed sort. The actual records to be sorted (which may be long strings) need not be appended to the sortkeys, which would create a second copy of each record. Using the indexed sort, the records may be recovered after the sort from the original data, using the sorted indexes.

The Sort::Maker module

Sort::Maker is on CPAN and implements the GRT forall types of Perl values.

Conclusions

Packing of subkeys into strings that can be compared lexicographically improves the performance of all sorting techniques, relative to the usual method of comparing the individual subkeys in pairs.

Packing the operands with the sortkeys allows the sort to be done using the default ascending lexicographic comparison (without a sortsub). This yields a markedly faster sort than the Orcish Maneuver or the Schwartzian Transform. The sorting process may approximate O(N) behavior, because the O(N*logN) time for the sort itself is small compared to the time required to extract the sortkeys.

The packed-sortkey sort may be written explicitly, or the new Sort::Maker module may be used.

Acknowledgments

This idea was brought to our attention by Michal Rutka [12]. John Porter participated in initiating this project and reviewed a draft of the paper.

References

1. The sort function man page, http://www.perl.com/CPAN/doc/manual/html/pod/perlfunc/sort.html

2. Kernighan, B. W. & Pike, R., (1999). The Practice of Programming, p. 41. Addison-Wesley.

3. Pike, R. (1989). Notes on Programming in C, http://wwwwbs.cs.tu-berlin.de/~jutta/c/pikestyle.html

4. Knuth, D. E. (1998). The Art of Computer Programming : Sorting and Searching (Vol 3, 2nd ed), chap. 5. Addison-Wesley.

5. Sedgewick, R. (1983). Algorithms, chap. 10. Addison-Wesley.

6. ANSI/ISO 9899-1992, sect. 4.10.5.2. American National Standards Institute.

7. Hall, J. N., Sort::Fields -- Sort lines containing delimited fields, http://www.perl.com/CPAN/modules/by-module/Sort/JNH/

8. Hall, J. N. (1998). Effective Perl Programming, p. 48. Addison-Wesley.

9. How do I sort an array by (anything)?, http://www.perl.com/CPAN/doc/manual/html/pod/perlfaq4.html#How_do_I_sort_an_array_by_anyth

10. Christiansen, T. & Torkington, N. (1998). The Perl Cookbook, Recipe 4.15: "Sorting a List by Computable Field". O′Reilly.

11. Christiansen, T., Far More Than Everything You′ve Ever Wanted to Know About Sorting, http://www.perl.com/CPAN/doc/FMTEYEWTK/sort.html

12. Rutka, M., in comp.lang.perl.misc. http://x4.dejanews.com/[ST_rn=ps]/getdoc.xp?AN=397853353)

Appendix A: Benchmarks

A caveat: Useful benchmarking depends on judicious isolation of relevant variables, both in the algorithms being benchmarked and in the data sets used. Different implementations may give different relative results even with the same algorithms and data. Thus all such results should be verified under your own conditions. In short, your mileage may vary.

In the following benchmarks, all data represent the time (in microseconds) per line in the input data, which averages 35 characters per line. All named arrays and hashes are preallocated, which reduces the variance in the measurements due to storage allocation.

Benchmark A1. Trivial sorts

Control

@out = @in;

Default

@out = sort @in;

Reverse

@out = reverse sort @in;

Explicit

@out = sort{ $a cmp $b } @in;

Insensitive

@out = sort{ lc $a cmp lc $b }@in;

Number of lines:

100

1000

10K

100K

Control

5

6

7

8

Default

9

13

19

25

Reverse

9

14

19

26

Explicit

17

25

37

50

Insensitive

47

62

91

119

Benchmark A2. Naive sorts (IP addresses)

Number of lines:

100

1000

10K

100K

Separate subkeys

697

1251

1732

2758

Packed sortkeys

583

1002

1363

1814

Benchmark A3. Cached sorts (packed sortkeys)

Number of lines:

100

1000

10K

100K

Caching

66

75

85

74

Sorting

49

87

122

164

Total cached sort

116

163

215

240

Orcish Maneuver

125

168

221

256

Benchmark A4. Advanced packed-key sorts

Number of lines:

100

1000

10K

100K

ST

?

?

?

?

Anon arrays

80

84

84

75

Sorting

27

47

76

97

Retrieval

13

18

20

17

One statement

116

150

177

191

Packed Default

?

?

?

?

Packing

61

63

65

67

Sorting

9

12

18

25

Retrieval

12

12

13

12

One statement

73

79

86

93

Benchmark A5. Another look at a trivial sort

Insensitive

@out = sort{ lc $a cmp lc $b }@in;

Packed

@out = map substr($_,1 + rindex $_, "\0")=>sort => map "\L$_\E\0$_"=> @in;

Number of lines:

10

100

1000

10K

100K

Insensitive

19

38

62

91

118

Packed

22

22

24

25

27

Benchmark A6. Two-dimensional packed-sortkey sorts

Number of lines:

100

1000

10K

100K

ST

243

314

359

435

Index

200

285

323

259

Appendix B: Explicit packed-default sorts

B1. Creating and combining sortable string subkeys

This is the preprocessing pass (the first map executed).

@sorted = map ... => sort =>map KEY($_) . $_ => @data;

To create and combine the subkeys and the operand to be sorted, any combination of concatenation, interpolation, pack, or sprintf may be used, the latter two with simple or compound formats.

Fixed-length strings (ascending):

simple interpolation

pack('... An ...', ...) sprintf('... %s ...', ...)

Fixed-length strings (descending):

Bit-complement the string first.

$subkey = $string ^"\xFF" x length $string

Then handle as an ascending fixed-length string.

Null bytes ("\0") are used to terminate string subkeys of varying length, as that ensures lexicographic ordering. If a string subkey may contain a null byte, then it must be of fixed length. If any of the operands to be sorted may contain null bytes, then every subkey must have fixed length.

Varying-length strings (ascending):

Terminate the string with a null byte, to separate it from succeeding subkeys or the operand.

interpolation: "$string\0"

pack('... A* x ...', ...)

sprintf('... %s\0 ...', ...)

Varying-length strings (descending):

Make a prepass over the data to find the length of the longest string.

my $len = 0;$len < length and $len = lengthfor map KEY($_) => @data;

Then null-pad each string to that length and proceed as above for fixed-length strings (descending).

$subkey = pack("a$len", $string)^ "\xFF" x $len

Unsigned 32-bit integers (ascending):

Pack or zero-pad to fixed length.

Preferred -- only 4 bytes:

pack('... N ...', ...)

Readable -- but 10 bytes:

sprintf('... %.10u ...', ...)

Signed two′s-complement 32-bit integers (ascending):

Bias to unsigned by xoring the sign bit, then treat as unsigned.

$subkey = pack('N',$number ^ (1 << 31));

Floating-point numbers (ascending):

This code assumes that floating-point numbers are represented in binary using IEEE format. Create a subroutine that packs a double in network order (big-endian).

BEGIN {my $big_endian =pack('N', 1) eqpack('L', 1);sub float_sort ($) {($big_endian ?pack 'd', $_[0] :reverse pack 'd', $_[0]) ^($_[0] < 0 ? "\xFF" x 8 :"\x80" . "\x00" x 7)}$subkey = float_sort($number);

Descending integers or floating-point numbers:

Negate the value, then use the appropriate one of the above.

B2. Extracting the operands from the sorted strings

This is the postprocessing pass (the second map executed).

@sorted = map RETRIEVE($_) =>sort => map ... => @data;

If all the subkeys have known length, use the total length:

Preferred for efficiency:

@sorted =map substr($_, $length) =>...

TMTOWTDI:

@sorted =map unpack("x$length A*",$_) => ...

If any of the subkeys has varying length, make sure that the last character in the complete packed sortkey is a null byte, then search for it from the right:

Preferred for efficiency:

@sorted = map substr($_,1 + rindex $_, "\0") => ...

TMTOWTDI:

@sorted =map (split /\0/)[-1] => ...@sorted = map /([^\0]+)$/ => ...

Appendix C: The Sort::Maker module

GO TO TOWN, URI! ...



總結

以上是生活随笔為你收集整理的Perl Sort的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

成人中文字幕在线观看 | 99久久免费看 | 精品久久国产精品 | 操久久网| 五月天婷亚洲天综合网精品偷 | 欧美一区二区日韩一区二区 | 亚洲 欧美 日韩 综合 | 久久激情视频免费观看 | 国产成人精品久 | 国产在线久久久 | 欧美色图东方 | 黄污视频网站 | 日韩欧美综合在线视频 | 91在线视频在线观看 | 黄色一级在线免费观看 | 亚洲国产大片 | 欧美成人在线网站 | 91视频高清免费 | 成年人在线免费看 | 综合久色 | 久久免费的视频 | 国产男女免费完整视频 | 国产亚洲欧美在线视频 | 麻豆高清免费国产一区 | 国产一区影院 | 成人在线视频免费看 | 天堂av网站 | 四虎在线免费观看 | 免费av大片| 黄色片视频在线观看 | 国产精品精品久久久 | 亚洲精品字幕在线观看 | 国产欧美三级 | 亚洲aⅴ一区二区三区 | 国产精品无av码在线观看 | 91九色老| 在线观看一级视频 | 久久看免费视频 | 亚洲欧洲一区二区在线观看 | 天天操天天色天天射 | 一区二区三区四区五区在线 | 精品国产一区二区三区四区在线观看 | 麻豆传媒视频在线免费观看 | 超碰人人乐 | 久久不射电影网 | 最新超碰| 亚洲a在线观看 | 国产在线观看免 | 亚洲视频久久久 | 成全在线视频免费观看 | 久久久在线视频 | 色在线免费 | 亚洲伊人网在线观看 | 久久免费视频在线观看30 | 亚洲成色777777在线观看影院 | 91传媒免费观看 | 国产成人精品一区二区三区在线 | 午夜久久久久 | 欧美一二三四在线 | 久久这里只有精品1 | 国产成人精品一区二 | 久久久午夜精品理论片中文字幕 | 国产视频中文字幕 | 免费电影一区二区三区 | 日韩欧美专区 | 丝袜美腿av | 日韩黄色一区 | 高清免费在线视频 | 久草影视在线观看 | 国产精品视频永久免费播放 | 在线精品播放 | 国产一区欧美在线 | 天天操比 | 三级黄色a | 久久视频在线观看中文字幕 | 人人精久 | 黄色大片入口 | 免费成人av在线 | 中文字幕乱码亚洲精品一区 | a特级毛片 | 激情www | 国产无遮挡又黄又爽馒头漫画 | 五月婷婷欧美视频 | 日韩电影在线观看一区二区三区 | 免费a网站 | 1024久久| 日韩欧美在线第一页 | 中文字幕av一区二区三区四区 | 色婷婷综合久色 | 涩涩网站在线观看 | 天天爱天天操天天射 | 中文av网| 亚洲激情p | 99免费在线观看视频 | 伊人狠狠色 | 人人讲下载 | 黄色高清视频在线观看 | 99久久精品费精品 | 在线观看蜜桃视频 | 午夜国产福利在线观看 | 青草视频在线 | 亚洲精品美女免费 | 岛国一区在线 | 久久久精品国产免费观看一区二区 | 日韩电影在线观看一区二区 | 国产又粗又猛又爽又黄的视频免费 | 一区二区三区视频网站 | 91av资源在线 | 亚洲女在线 | 亚洲精品成人免费 | 国产又粗又猛又黄又爽的视频 | 精品国产理论 | 免费亚洲电影 | www黄色av| 精品一区二区在线免费观看 | 天天天操天天天干 | 欧美精品久久久久久久久免 | 免费看一级片 | 色偷偷888欧美精品久久久 | 国产一区二区午夜 | 久久久久久国产精品 | 91视频在线 | av免费电影网站 | 不卡av电影在线观看 | 日韩一区二区免费播放 | 日韩欧美一区视频 | 亚洲小视频在线 | 在线观看国产区 | 91视频成人免费 | 久久久受www免费人成 | 日韩欧美精品一区二区 | 国产日韩精品欧美 | 日韩av手机在线看 | 91九色视频在线播放 | 国产精品九九久久99视频 | 永久免费的av电影 | 色婷婷一区 | 欧美日韩aa | 999国产在线 | 成人久久精品视频 | 国产日韩在线播放 | www.久久色.com | 色综合欧洲| 狠狠躁日日躁狂躁夜夜躁 | 在线观看久 | 91精品久久久久久综合乱菊 | 中文字幕传媒 | 欧美视屏一区二区 | 2019精品手机国产品在线 | 国产一二三在线视频 | 久久av高清| 欧美日韩精品在线观看视频 | 毛片网在线观看 | 中文字幕 国产 一区 | 日本护士撒尿xxxx18 | 激情影音先锋 | 91久久偷偷做嫩草影院 | 黄色片视频在线观看 | 日韩va欧美va亚洲va久久 | 久久亚洲综合国产精品99麻豆的功能介绍 | 久久久久久蜜av免费网站 | 在线精品亚洲一区二区 | a久久久久久 | 成人资源在线播放 | 日韩网站在线看片你懂的 | 免费性网站 | 一区二区三区精品在线视频 | 久久国产电影院 | 成人app在线免费观看 | 日韩视频欧美视频 | 国产精品18毛片一区二区 | 国产美女视频网站 | 国产理论影院 | 久久久久综合精品福利啪啪 | 欧美污污视频 | 国产精品日韩高清 | 五月天综合色激情 | 国产一区二区在线免费视频 | 免费av看片 | 亚洲激情六月 | 免费av视屏 | 91麻豆操 | 在线观看www. | 亚洲最新av网址 | 欧美精品一区二区在线观看 | 成年人精品 | 亚洲国产精品女人久久久 | 色在线中文字幕 | 久久系列| 亚洲天堂精品视频在线观看 | 九九热在线免费观看 | 国产精品免费观看国产网曝瓜 | 国产精品一区二区三区视频免费 | 国产亚洲精品久久久久久大师 | 91看片淫黄大片91 | 国产亚洲激情视频在线 | 久久99精品国产99久久6尤 | 91av色| 国产精品区在线观看 | 日本精品视频在线播放 | 日韩免费视频线观看 | 国产视频精品免费播放 | 日本久久电影 | 四虎影视成人永久免费观看视频 | 国产日韩精品欧美 | 国产999精品久久久影片官网 | 最新久久久| 激情欧美日韩一区二区 | 亚洲激情一区二区三区 | 精品久久久久久久久久久院品网 | 日本中文字幕在线播放 | 国产自产高清不卡 | 亚洲综合在线五月 | 911免费视频 | 日韩一区精品 | 在线观看www. | 中国成人一区 | 亚洲男男gaygay无套同网址 | 日韩av播放在线 | 黄色大片日本 | 91插插影库 | 久久久久久久久久影视 | 日韩免费电影网站 | 黄污网站在线 | 成人免费 在线播放 | 粉嫩av一区二区三区四区在线观看 | 日日干日日操 | 亚洲欧洲国产精品 | 中字幕视频在线永久在线观看免费 | 久久国际影院 | 夜夜夜影院 | 欧美午夜久久 | av在线精品 | 亚洲影院色 | 亚洲视频456| 五月天中文在线 | 亚洲,国产成人av | 在线激情av电影 | 亚洲一一在线 | 亚洲日韩中文字幕 | 蜜臀av网址 | 久久伊人操| 在线观看午夜av | 美女很黄免费网站 | 国产视频九色蝌蚪 | 久久er99热精品一区二区三区 | www.色的| 日韩免费视频在线观看 | av再线观看 | 黄色a一级片 | 日日干夜夜草 | 91av视频播放| 成人宗合网 | 91色影院| 久久精品综合一区 | 日本中文乱码卡一卡二新区 | 成人免费观看视频大全 | 亚洲精品视频免费在线观看 | 91九色国产视频 | 国产精品欧美久久久久三级 | 亚洲 欧美 综合 在线 精品 | 欧美色图视频一区 | 国产在线精品区 | 精品久久久久久久久久久久 | 91av99| 日韩电影在线观看中文字幕 | 国产一区免费在线 | av在线播放观看 | 国产丝袜一区二区三区 | 国产精品破处视频 | 中文字幕123区 | 日日夜夜天天综合 | 中文一二区 | 字幕网资源站中文字幕 | 精品国产乱子伦一区二区 | 亚洲一区天堂 | 黄色大片免费网站 | 成片免费| 国产中文字幕一区 | 久久精品之 | 日韩精品中文字幕在线观看 | 中文字幕第一页在线播放 | 欧美国产一区二区 | 黄色成人影视 | 亚洲天堂激情 | 国产精品永久久久久久久久久 | a精品视频| 午夜视频在线瓜伦 | 毛片网在线播放 | 久久99精品国产麻豆婷婷 | 午夜视频一区二区 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 国产精品成人久久久 | 亚洲成人资源网 | 97精品超碰一区二区三区 | 日本黄色大片儿 | 夜夜狠狠 | 国产精品久久久久久高潮 | 亚洲aⅴ乱码精品成人区 | 色婷婷免费视频 | 久久免费精品国产 | 手机av观看 | 成人黄色电影在线观看 | 四虎成人精品永久免费av九九 | 狠狠狠狠狠狠天天爱 | 黄色软件网站在线观看 | 免费情趣视频 | 国产成人三级一区二区在线观看一 | 中文字幕高清在线播放 | 9i看片成人免费看片 | 中文字幕超清在线免费 | 欧美 日韩 国产 中文字幕 | 久久久久成人精品免费播放动漫 | 五月在线| 欧美日韩亚洲在线观看 | 国产精品美女久久久久久2018 | 在线不卡中文字幕播放 | 日韩欧美视频一区二区三区 | 久久精品国产精品亚洲 | 18久久久久久 | 91成品人影院 | 人交video另类hd | 国产精品自产拍在线观看桃花 | 久久精品影片 | 亚洲女在线 | 午夜成人免费影院 | 午夜精品电影一区二区在线 | 亚洲干 | www.久草.com | 麻豆视频在线看 | 18国产精品福利片久久婷 | 日韩欧美一区二区在线观看 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 亚洲另类交 | 中文字幕在线视频免费播放 | 国产不卡一 | 成人电影毛片 | 国产精品淫片 | 欧洲精品亚洲精品 | 国产一级片免费播放 | 在线观看av黄色 | av电影一区 | 久久久精品在线观看 | 奇米网在线观看 | 国内精品久久久久影院优 | 亚洲激情精品 | 日韩另类在线 | 国产精品av久久久久久无 | 欧美福利视频 | 日韩中文在线电影 | 四虎影视精品 | 99综合电影在线视频 | 国产小视频在线播放 | 91精品国产乱码久久桃 | 国产精品手机在线观看 | 九九久久在线看 | 久久国产精品久久w女人spa | 日韩一区二区久久 | 天天操天天操天天操天天操天天操天天操 | 国产精品免费久久久 | 黄色成人在线网站 | 在线97 | 亚洲欧美国产精品久久久久 | 9色在线视频 | 一区二区在线电影 | 日韩av午夜在线观看 | 五月激情久久 | 99视频国产精品免费观看 | 国内精自线一二区永久 | 国产黄色片在线免费观看 | 欧美精品久久久久久久久久久 | 日日夜夜天天综合 | 国产亚洲人 | 81国产精品久久久久久久久久 | 日韩三级久久 | 99视频精品全国免费 | 日韩和的一区二在线 | 开心色停停 | 成人午夜影院在线观看 | 福利视频网站 | 91精品国自产在线观看欧美 | 五月天六月丁香 | 美女网站色在线观看 | 久久99久国产精品黄毛片入口 | www.xxxx欧美 | 精品久久久久久久久久久久 | 91久久国产露脸精品国产闺蜜 | 一区二区三区四区五区六区 | 国产精品免费一区二区三区在线观看 | 国产精品久久久久久久久毛片 | 久久99深爱久久99精品 | 视频一区二区在线观看 | 韩日色视频 | 三级av中文字幕 | 中文字幕成人 | 一区二区三区在线观看 | 婷婷网五月天 | 免费99视频 | 国产免费久久久久 | 天天干,狠狠干 | 在线观看av小说 | 日日爽天天 | 国产一区高清在线 | 粉嫩av一区二区三区四区 | 国产爽视频 | 天天色天天综合 | 在线观看午夜 | 亚洲综合精品视频 | 一区二区 精品 | 国产精品日韩欧美 | 五月天激情电影 | 久久久九色精品国产一区二区三区 | 97视频免费在线 | 午夜精品999 | 亚洲最大激情中文字幕 | 亚洲视频网站在线观看 | 中文字幕美女免费在线 | 中文字幕在线观看三区 | 日韩免费视频在线观看 | 日本久久免费电影 | www五月天婷婷 | 日韩精品一区二区三区中文字幕 | 久久久久久久综合色一本 | 91插插视频 | 日本xxxxav | 日韩性片 | 国产高清不卡在线 | 在线观看日本高清mv视频 | 开心色激情网 | 成人免费网站在线观看 | 9999精品视频 | 日本在线成人 | 欧美黑吊大战白妞欧美 | 国产精品女同一区二区三区久久夜 | 精品久久1 | 99re6热在线精品视频 | 国产激情久久久 | 91在线看免费 | 在线91播放| 午夜视频免费 | 国产高清视频在线播放 | 亚洲欧美va| 国产日韩在线播放 | 国产99视频在线观看 | 久久久精品免费观看 | 天天干一干 | 啪啪激情网 | 精品高清美女精品国产区 | 99爱视频在线观看 | 午夜久久福利影院 | 一区av在线播放 | 91传媒在线观看 | 亚洲精品午夜一区人人爽 | 久久 精品一区 | 亚洲免费视频在线观看 | 精品在线视频观看 | 国产精品久久久久aaaa | 国产一区二区三区免费观看视频 | 一区二区三区在线视频111 | 久久网址 | 国语麻豆| 亚洲婷婷综合色高清在线 | 日日草夜夜操 | 国产日产精品久久久久快鸭 | av免费福利 | 免费黄色av片 | 天堂av网址 | 日日射av| 日本精品在线视频 | av成人免费在线 | 在线观看欧美成人 | 成人免费在线视频 | 东方av免费在线观看 | 91精品久久久久久久91蜜桃 | 国内外成人在线视频 | 在线免费精品视频 | 日韩免费中文 | av免费在线看网站 | 国产色在线视频 | 91精品亚洲影视在线观看 | 日韩经典一区二区三区 | 久久综合在线 | 亚洲永久精品国产 | 国产不卡视频在线播放 | 国产又粗又硬又爽的视频 | 麻豆成人在线观看 | 久久午夜视频 | 在线免费观看黄色大片 | 国产午夜三级 | 成人xxxx| 日韩美精品视频 | 久久久久久久国产精品 | 久久免费视频在线 | 黄网站污| 国内精品久久久久影院一蜜桃 | 中文字幕成人在线观看 | 激情五月激情综合网 | 亚洲成人午夜在线 | 色视频在线观看 | 六月丁香婷婷网 | 亚洲精品乱码久久久一二三 | 国产字幕在线观看 | 国产一区高清在线 | 日韩大陆欧美高清视频区 | 亚洲精品在线免费观看视频 | 在线视频你懂 | 99国产视频 | 欧美日韩后 | 四虎成人精品永久免费av | av成人在线电影 | 99久久这里只有精品 | av在线在线 | 人人射人人澡 | 婷婷五综合 | 久久一精品 | 亚洲激情视频在线 | av一区二区三区在线 | 四虎在线观看 | 婷婷色网视频在线播放 | 91精品国产高清自在线观看 | 成年人电影毛片 | 日韩一二区在线 | 97在线观看 | 久久艹精品 | 亚洲黄色高清 | 青青河边草免费观看完整版高清 | 久久99久久99精品免费看小说 | 草久久久久久 | www.天天射.com | 欧美性超爽 | 中文字幕人成乱码在线观看 | 国产一区二区三区免费在线 | 91精品国产一区二区三区 | 97色综合| 久久久久国产精品一区二区 | 国产亚洲在线视频 | 国产视频精品在线 | 欧美夫妻生活视频 | 黄视频色网站 | 91在线看黄 | 日韩在线免费电影 | 日韩精品一区二区不卡 | 国产日韩欧美视频在线观看 | 黄色软件大全网站 | 天天综合亚洲 | 国产91成人 | 黄色精品一区二区 | 久久久久亚洲精品成人网小说 | 国产美女精品视频 | 日韩一区二区三区高清免费看看 | 一区二区精品在线观看 | 国产99久久久国产精品免费看 | 91桃色国产在线播放 | 国产精品久久99综合免费观看尤物 | 久久精品国产99国产 | 黄色大片国产 | 日本最新一区二区三区 | www国产亚洲 | 亚洲成人蜜桃 | 伊人婷婷久久 | 99 久久久久 | 噜噜色官网 | 成人免费在线视频观看 | 日本mv大片欧洲mv大片 | 欧美在线视频免费 | 日韩精品一区在线播放 | 一级免费av | 天天躁天天躁天天躁婷 | 99热精品在线 | 国产日本三级 | 免费在线观看日韩视频 | 亚洲丁香久久久 | 免费av片在线 | 中文字幕亚洲综合久久五月天色无吗'' | www国产一区| 国产精品白浆 | 婷婷激情av | 在线播放 日韩专区 | 91久久精品日日躁夜夜躁国产 | 2019国产精品 | 黄色视屏免费在线观看 | 日本在线观看一区二区三区 | 天天操天天爱天天爽 | 国产专区一 | 国产精品久久久久免费观看 | 国产97av| www.狠狠插.com | av黄色在线 | 麻豆系列在线观看 | 国产香蕉视频 | 亚洲欧美日韩不卡 | 91在线精品观看 | 激情大尺度视频 | 亚洲国产久 | 国色天香在线 | 国产精品一区在线播放 | 久草在线99 | 99视频在线观看免费 | 久久国产三级 | 国产91av视频在线观看 | 麻豆视频在线免费看 | 激情伊人五月天久久综合 | 国产精品美女网站 | 亚洲精品女人久久久 | 欧美日韩啪啪 | 91人人人 | 亚洲一区视频免费观看 | 国产精品欧美久久久久无广告 | 欧美国产日韩激情 | 中文伊人 | 人人澡视频 | japanesexxx乱女另类 | 一区二区三区免费在线观看视频 | 91精品人成在线观看 | 看v片| 91视频 - x99av| 日日夜夜网 | 一区二区中文字幕在线观看 | 亚洲激情av | 国产高清在线精品 | 国产一级a毛片视频爆浆 | 最近中文字幕免费av | 亚洲精品国偷拍自产在线观看蜜桃 | 国产精彩视频一区二区 | 亚洲精品久久视频 | 在线观看黄色大片 | 国产精品久久久久久久久婷婷 | 国产精品亚洲精品 | av福利在线看 | 亚洲视频六区 | 久久久久国产精品免费网站 | 日韩啪啪小视频 | 蜜桃av观看 | 激情自拍av | 9幺看片 | 久久久久综合精品福利啪啪 | 午夜国产福利在线 | 免费十分钟 | 久草电影在线 | 精品国产亚洲一区二区麻豆 | 3d黄动漫免费看 | 91av原创| 极品中文字幕 | 亚洲一级特黄 | 精品视频免费看 | 亚洲精品视频第一页 | 免费视频 你懂的 | 91干干干| 综合久久久久 | 91视频免费看 | 天天干天天操天天搞 | 91亚·色| 久久成人精品电影 | 五月天丁香视频 | 日韩亚洲国产精品 | 69精品久久久 | 久久国产欧美日韩精品 | 天天干人人干 | 成年人视频在线 | 国产精品久久久久久久久免费看 | 五月天伊人网 | 夜色资源网 | 国产高清免费在线播放 | 婷香五月 | 亚洲精品欧洲精品 | 久久久久久影视 | 国产精品美女久久久网av | 在线看一区 | 激情六月婷婷久久 | 丁香五月亚洲综合在线 | 国产啊v在线观看 | 欧美精品一级视频 | 91天天操 | 国产成人三级一区二区在线观看一 | 91精品综合| 91资源在线 | 欧美视频国产视频 | 亚洲精品在线免费播放 | 欧美福利视频一区 | 黄色的网站在线 | 涩涩网站在线 | 日日操操操 | 一区三区视频在线观看 | 激情网五月婷婷 | 久久麻豆视频 | 欧美一级欧美一级 | 97av影院| 中文字幕三区 | 日韩99热| 天天综合网天天综合色 | 天天操天天干天天 | 色狠狠婷婷 | 国产一区久久久 | 99在线看| 国产成人av在线影院 | 日韩在线第一 | 久久国产欧美日韩精品 | 成年人免费电影在线观看 | 国产精品久一 | 九九99| 91精品人成在线观看 | 一本一本久久a久久精品综合小说 | 欧美另类视频 | 久久久久亚洲精品男人的天堂 | 水蜜桃亚洲一二三四在线 | av蜜桃在线| 亚州成人av在线 | 99精品黄色片免费大全 | 国产亚洲精品精品精品 | 日韩一区二区在线免费观看 | 国内免费久久久久久久久久久 | 在线观看国产成人av片 | 久久av在线播放 | 日日夜夜人人精品 | 国产字幕在线看 | 色综合久 | 国产免费一区二区三区最新 | 久久亚洲在线 | 色 免费观看 | 日韩精品一区二区三区高清免费 | 国产黄色免费 | 日日夜夜狠狠干 | 久保带人| 国产拍揄自揄精品视频麻豆 | 亚洲综合少妇 | 亚洲激精日韩激精欧美精品 | 成人免费网视频 | 日韩有码在线观看视频 | 日韩精品综合在线 | 808电影 | 99在线热播精品免费99热 | 亚洲国产精品久久久久久 | 久久天天操 | 91福利社区在线观看 | 日本中文字幕影院 | 狠狠色丁香婷婷综合橹88 | 激情在线网址 | 亚洲精品电影在线 | 奇人奇案qvod| 精品在线观看一区二区 | 亚洲伦理电影在线 | 久久精品看片 | av一级片 | 成人在线视频一区 | 91亚洲精品久久久蜜桃网站 | 国产一线天在线观看 | 日韩电影一区二区在线观看 | 久久国产麻豆 | 奇米影视8888在线观看大全免费 | av观看网站 | 久久久国产精品亚洲一区 | 婷婷午夜 | 国产成人777777 | 久青草影院 | 激情av资源 | 国产精品久久久免费看 | 欧美性极品xxxx娇小 | 免费中文字幕视频 | 日韩资源在线播放 | 国产成人精品免费在线观看 | 国产成人在线播放 | av观看免费在线 | 99这里只有久久精品视频 | 天天色天天射天天综合网 | 九九热免费在线观看 | 免费看网站在线 | 亚洲精品免费观看视频 | 国产成人性色生活片 | 国产精品亚洲精品 | 色香com. | 久久久久这里只有精品 | 黄色av一区二区 | 人人爱人人舔 | 成人av电影免费观看 | 日韩精品一区二区三区水蜜桃 | 日产av在线播放 | 亚洲第一区在线观看 | 免费福利在线观看 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 久久久久亚洲精品成人网小说 | 在线91播放 | 99视频在线精品国自产拍免费观看 | 亚洲开心激情 | 精品国内自产拍在线观看视频 | 精品视频成人 | 日韩欧美一区视频 | 免费在线国产精品 | sm免费xx网站 | av一本久道久久波多野结衣 | 夜夜操夜夜干 | 免费a视频 | 久久精品视频网 | 日韩欧美成 | 国产精品一区二区三区久久 | 国产精品亚洲精品 | 亚洲国产精品电影在线观看 | 国产精品午夜久久久久久99热 | 中文字幕二区在线观看 | 友田真希x88av | 在线视频 日韩 | 91亚洲国产| 在线免费观看视频 | 在线免费观看欧美日韩 | 国产一区二区在线观看视频 | 免费在线观看一区二区三区 | 国内精品在线观看视频 | 91电影福利| 欧美精品你懂的 | 在线观看免费观看在线91 | 综合在线亚洲 | 97在线免费 | 狠狠躁日日躁狂躁夜夜躁av | 狠狠躁日日躁夜夜躁av | 97夜夜澡人人双人人人喊 | 国产不卡视频在线 | 欧美视频在线观看免费网址 | 久久精品欧美一区 | 草久电影 | 9999亚洲| 伊人中文字幕在线 | 欧美日韩性视频 | 91在线精品秘密一区二区 | 黄色成人av网址 | 国产剧情在线一区 | 久久99操| 天天射天天干 | 精品一区二区在线免费观看 | av免费观看高清 | 99热这里有精品 | 中文一区二区三区在线观看 | 日本不卡一区二区三区在线观看 | 亚洲欧美视频在线播放 | 日韩欧美高清一区二区三区 | 美女久久久久久久久久久 | 丁香花在线观看免费完整版视频 | 97精品国产一二三产区 | 国产一区私人高清影院 | 天堂av在线7| av综合网址| 亚洲激情一区二区三区 | 日韩欧美国产免费播放 | 欧美另类巨大 | 亚洲精品乱码久久久久久久久久 | 日日干夜夜骑 | 精品国偷自产国产一区 | 日韩精品在线观看av | 五月天综合色激情 | 蜜臀一区二区三区精品免费视频 | 99精品视频在线观看 | 欧美另类v | 69国产盗摄一区二区三区五区 | 麻豆观看 | 91在线播放视频 | 五月天高清欧美mv | 夜夜摸夜夜爽 | 999视频网 | 亚洲全部视频 | 国产亚洲精品久久久久久无几年桃 | 黄av在线| 欧美巨大荫蒂茸毛毛人妖 | 久久久电影网站 | 日韩理论视频 | 伊人天天操 | 91原创在线观看 | mm1313亚洲精品国产 | 国产999精品久久久 免费a网站 | 国产精品一区二区免费 | 国产黄 | 玖玖精品在线 | 伊人日日干| 四虎影视成人精品 | 国产精品高 | 久久久久免费电影 | 国产精品99页 | 五月婷婷深开心 | 高清国产午夜精品久久久久久 | 欧美在线观看视频免费 | 92精品国产成人观看免费 | 开心激情网五月天 | 国产九九热| 亚洲人成人在线 | 四川妇女搡bbbb搡bbbb搡 | 人人射人人射 | 国产黄色片免费 | 免费观看一级 | 国产剧情在线一区 | 最近中文字幕免费视频 | 日韩系列在线 | 免费观看一区二区 | 99视| 狠狠婷婷 | 91成年人在线观看 | 97视频总站 | 久久久免费在线观看 | 久久国产色| 色婷婷激情五月 | 亚洲va韩国va欧美va精四季 | a天堂最新版中文在线地址 久久99久久精品国产 | 久久久久高清毛片一级 | av福利在线 | 91av在线免费看 | 亚洲午夜精品电影 | 四虎国产精品永久在线国在线 | 91视视频在线直接观看在线看网页在线看 | 精品视频123区在线观看 | 久久综合五月天 | 婷婷综合在线 | 99精品视频免费在线观看 | 啪啪免费视频网站 | av资源免费在线观看 | 国产网红在线观看 | 国产精品日韩欧美一区二区 | 国产精品第10页 | 97碰碰精品嫩模在线播放 | 99免费看片 | 日韩欧美电影网 | 国产又粗又猛又黄视频 | 999精品在线| 国产成人在线观看免费 | 波多野结衣视频一区 | 99热 精品在线 | 狠狠色丁香婷婷综合最新地址 | 探花视频免费观看 | 日日干av | 久久精品99北条麻妃 | 成人av免费在线观看 | 亚洲国产网站 | 午夜色性片| 国产精品二区在线 | 樱空桃av| 精品久久网 | 激情 一区二区 | 视频高清 | 国产一卡二卡四卡国 | 久久久久久久久久久久国产精品 | 亚洲欧美在线观看视频 | 美女一区网站 | 一二三精品视频 | 国产乱视频| 97成人免费视频 | 午夜视频福利 | 在线色资源 | 在线你懂 | 在线黄色av | 五月激情av | 91桃色在线播放 | 久久在线影院 | 国产人成看黄久久久久久久久 | 婷婷香蕉| 久久国色夜色精品国产 | 日韩av女优视频 | 国产96av | 人人网av| 999国产精品视频 | 99久久久国产精品免费99 | 亚洲一区二区三区毛片 | 一二三久久久 | 中文字幕av在线播放 | 成人av高清| 久久av高清 | 日韩,精品电影 | 久久9精品| 综合久色| 精品综合久久 | 中文字幕一区三区 | 999久久久 | 五月天天色 | 午夜精品久久久久久99热明星 | 国产精品你懂的在线观看 | 波多野结衣电影久久 | 色婷婷成人网 | 国产无套视频 | 国产不卡片 | 9999亚洲| 激情五月***国产精品 | 成人在线视频论坛 | 日韩欧美综合精品 | 久久国产精品区 | 欧美一区二区在线免费观看 | 成人在线观看资源 | 操处女逼 | 伊人五月天婷婷 | 毛片在线播放网址 | 精品一区二区在线免费观看 | 国产91综合一区在线观看 | a色视频 | 在线观看播放av | 久久精选 | 91免费在线看片 | a色视频 | 日韩理论电影在线观看 | 日韩中文字幕国产 | 黄色精品一区二区 | 国产中文自拍 | 亚洲v欧美v国产v在线观看 | 久久怡红院 | 97超碰超碰久久福利超碰 | 蜜臀av夜夜澡人人爽人人 |