Find the element K small in the series (C language version)

Source: Internet
Author: User

Today is looking at the algorithm: C language Implementation, in the quick sort that chapter the last section tells the idea of using the quick sort, the quick sort after each partition on the left side of the pivot element is smaller than the pivot, the number of the pivot to the right is larger than the pivot (or equal), and the division after the pivot itself is placed (in order) its own position, Judging the size of the pivot subscript and K after each partition can quickly find out the number of K in the series.

After reading, I think that since the use of fast-sorting ideas can quickly find the number of K small, then can use the idea of counting sorting to find the number of K small, carefully think, completely can! The count sort is to use a count array C to record the number of occurrences of each of the different values in the array to be sorted, then the number of elements less than or equal to the number I can be obtained by iterating through the Count array C, using c[i] + = C[i-1], and then following the C[i] You can put the number of values in the sorted array to the position where it should be. So how do you use this count array c? After iterating over the Count array (execute c[i] + = C[i-1]), C[i] represents the number of elements in the array to be sorted less than or equal to I, and c[i-1] represents the number of elements with a value less than or equal to i-1, if c[i-1] < K and K <= C[i], Then the number of K small in the sorted array must be the number of the value I! The search will be over. So I just need to find the first one that satisfies the condition K <= C[i].

In the specific algorithm before the first agreement on the number of K small for the sequence of numbers starting from 0 k-1 number, that is, k>0.

Let's start with the simplest algorithm:


First, sort the entire sequence and take the number of k-1.

This method is simple and rough, the number of series by the way from small to large, you can easily get the numbers of k-1, but this method makes the whole sequence of order, did too much work.


second, the use of choice to sort

The first method is simple and straightforward, but since we only need to get the number of K small for the whole sequence, we can choose to sort the idea: select sort each iteration of the sequence is selected from the remaining n-i number of the smallest number and the first I value to Exchange, Until I equals N-1, the whole sequence is orderly. For the selection of the number of K small, we only need to make a K-pass selection to get the number of small K.

The code is as follows:

Using the idea of sorting by choice, find K-trip to find the element K small elements void Selectsortsearch (int array[], int size, int k) {    int minindex;    int i = 0;    int j = 0;    for (i = 0; i < K; ++i) {        minindex = i;        for (j = i + 1; j < size; ++j) {            if (Array[j] < Array[minindex]) {                minindex = j;            }        }        Swap (&array[i], &array[minindex]);    }    printf ("Find:%d\n", array[k-1]);} void swap (int *value1, int *value2) {    int temp = *value1;    *value1 = *value2;    *value2 = temp;}

This method is used in the case of a small K-value, the efficiency of this method and the selection algorithm and based on the counting sorting idea is much more efficient when the K value is small, but the efficiency of the square is reduced when the value of K is relatively large.


three, the choice algorithm

Algorithm Description:

Using the fast sorting method to rearrange the array a[l],...., A[r], return an integer I, satisfy a[l],....., a[i-1] All light rain a[i],a[i+1],...., a[r] are greater than or equal to a[i], if K equals I, Then our work is done. Otherwise, if k is less than I, then the left sub-sequence continues to be processed, and if I is greater than K, then the DAI continues to process the subsequence on the right.

The code is as follows:

//using the idea of recursive quick sorting to find the K-small dollar    vegetarian void Recquicksearch (int array[], int low, int. high, int k) {int index;    if (High < low) {//Note that <= return cannot be used here;    } index = Findpivotindex (array, low, high);        if (index = = k-1) {printf ("Find:%d\n", Array[index]);    return;    } if (Index > K-1) {recquicksearch (array, Low, index-1, K);    } if (Index < k-1) {Recquicksearch (array, index + 1, high, k);    }}int findpivotindex (int array[], int low, int. high) {int pivot = Array[low];        while (Low < high) {when (Low < high && Array[high] >= pivot) {--high;        } Array[low] = Array[high];        while (Low < high && Array[low] <= pivot) {++low;    } Array[high] = Array[low];    } Array[low] = pivot; return low;} 
The above is the recursive form of the selection algorithm, the following is a non-recursive form of the selection algorithm:
Using the idea of non-recursive quick sorting find the element of K small, void QuickSearch (int array[], int low, int. high, int k) {    int index = 0;    while (high >= low) {        index = findpivotindex (array, low, high);        if (index = = k-1) {            printf ("Find:%d\n", Array[index]);            break;        }        if (Index > K-1) {high            = index-1;        }        if (Index < k-1) {Low            = index + 1;}}}    


Iv. the idea of using counting sort

Algorithm Description:

after iterating over the Count array (execute c[i] + = C[i-1]), C[i] represents the number of elements in the array to be sorted less than or equal to I, and c[i-1] represents the number of elements less than or equal to i-1, if C[i-1] < K and K <= C[i], then the number of K small in the sorted array must be the number of the value I! The search will be over. So I just need to find the first one that satisfies the condition K <= C[i].

The code is as follows:

Use the idea of counting sorting to find the K-small element void Countsearch (int array[], int size, int k) {assert (Array! = NULL && size > 0); A count array that counts the number of occurrences of each different number in an array of arrays//due to the number of arrays in the array belonging to 0 ...    RANDMAX-1, so the size of the countarray is sufficient to accommodate the value of Randmax int *countarray = (int *) calloc (Randmax, sizeof (int));    Counts the number of occurrences of each different number in an array of arrays, after the end of the loop Countarray[i] indicates the number of occurrences of the value I in the array int index = 0;    for (index = 0; index < size; ++index) {countarray[array[index]]++;    }//possibly Countarray[0] is already larger than K if (Countarray[0] >= k) {printf ("find:0\n"); } else {//the number of numbers smaller than index, Countarray[i] indicates the number of elements in the array that are less than or equal to the number I for (index = 1; index < Randmax; ++in            DEX) {Countarray[index] + = countarray[index-1]; When the condition is first met, it represents the small number of K at the element less than or equal to index and greater than index-1 between if (Countarray[index] >= k) {printf ("Find:%d                \ n ", index);            break; }}} free (Countarray);}

Using the idea of counting sorting to find the small number of K although it is running fast, it also has the same disadvantage as counting sort, that is, the space complexity is too high, it is not suitable for a large range of element values in the series to find the number K small. Also, it is not suitable for cases where there are negative numbers in the series.


The idea of using heap sequencing (i.)

Algorithm Description:

For the heap sorting of the lookup array, only K-trips can be found to find the element K small.

Using a small top heap to maintain a heap with a size of initial magnitude, K-times heap rows can be obtained with the K-small element void heapSearch1 (int array[], int size, int k) {assert (Array! = NULL && S    ize > 0 && k < size);    int *heappointer = array-1;    Adjusts the array from the bottom up so that it becomes a heap int index = 0;    for (index = SIZE/2; index > 0;--index) {fixDown1 (heappointer, index, size); }//Swap heap top and last elements and adjust the heap structure//execute k times to get the element K small for (index = 0; index < K; ++index) {Swap (&heappointer[        1], &heappointer[size--]);    FixDown1 (Heappointer, 1, size); } printf ("Find:%d\n", Heappointer[size + 1]);}    The node from subscript index starts to adjust downward so that the tree becomes heap ordered (small top heap) void fixDown1 (int array[], int index, int size) {int i = index;    Int J = 2 * index; while (2 * i <= size) {//The node labeled I has children j = 2 * i;//Let J point left child//When I have right child and right child than left child hour, let J point to right child if (j + 1 &L        t;= size && array[j + 1] < Array[j]) {++j;        }//If the value of the element to be adjusted is less than the larger child, adjust the end exit loop if (Array[i] <= array[j]) {break;     }   Otherwise swap the element to be adjusted and its larger sub-node swap (&array[i], &array[j]); i = j;//let I point to the adjusted node to be adjusted}}

Constructing a heap of size n is less than 2N compared to the number of comparisons used to remove the K-min elements by less than 2k*lgn times, with a total of 2N + 2K*LGN comparisons.


Vi. The idea of using heap sequencing (II.)

The last idea is to use the heap sort of k-trip to get a small number of k, but this method needs to maintain an array of size n, and we need only a small element k, then we can use a large heap of size k to maintain the smallest number of k, and then use to find the remaining elements array [j] compared to the top element of the heap, if the heap top element value is set to array[j] compared to the top element of the heap, then the heap adjustment is made, and the top element of the heap after traversing the entire array is the element K small.

The code is as follows:

Maintain a large heap of size k, when the element in the array to find Array[i] is smaller than the top element of the heap, replace the top element of the heap with array[i],//and then adjust the heap structure so that it remains the nature of the large heap, so that the top element of the heap after traversing the entire array to be looked up is the K small element//    Heap sort, using a large top heap, from small to large sort void heapSearch2 (int array[], int size, int k) {int heapsize = k;    int *heap = (int *) calloc (heapsize + 1, sizeof (int));    int i = 0;    for (i = 0; i < heapsize; ++i) {heap[i + 1] = Array[i];    }//Bottom-up resize the array heap so that it becomes a large top heap for (i = HEAPSIZE/2; i > 0; i) {fixDown2 (heap, I, heapsize);    } int j = 0;            for (j = k; j < size; ++j) {if (heap[1] > Array[j]) {heap[1] = array[j];        FixDown2 (heap, 1, heapsize); }} printf ("Find:%d\n", heap[1]);}    The node from subscript index starts to adjust downward so that the tree becomes a heap-ordered void fixDown2 (int array[], int index, int size) {int i = index;    Int J = 2 * index; while (2 * i <= size) {//The node labeled I has children j = 2 * i;//Let J point to left child//When I have right child and right child is larger than left child, let J point to right child if (j + 1 &L        t;= size && Array[j] < Array[j + 1]) {++j; }//If the value of the element to be adjusted is greater than the larger child,Adjust end exit loop if (Array[i] > Array[j]) {break;        }//Otherwise swap the element to be adjusted and its larger sub-node swap (&array[i], &array[j]); i = j;//let I point to the adjusted node to be adjusted}}
A heap of size K requires a 2k comparison, and then compares the remaining n-k elements of the array with the top elements of the heap, comparing the number of n-k, if it is less than the top element of the heap, placing the heap top element value as the value, and then adjusting the heap to maintain the nature of the large top heap, which is 2 ( N-K) *lgk times comparison, so the total number of comparisons is 2k + (n-k) + 2 (n-k) *lgk = N + k + 2 (n-k) *lgk times comparison. This method uses a space that is proportional to K, so when K is small and n is large, there is a high time efficiency for finding elements in n elements that are small, and for the following keywords and other cases, the upper bound of the heap operations in this method is a small k relative n smaller is probably O (1)!

Find the element K small in the series (C language version)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.