分治算法四(查找第K小元素)

来源:互联网 发布:无损分区软件 编辑:程序博客网 时间:2024/06/11 18:30
1.问题描述

对于一个非有序的数组A[start..end],求数组中第k小的元素

2.解决思路

最直观的的方式,先对数组排序,复杂度为o(nlgn),但是这样复杂度太大,可以利用快速排序的思路,解决这个问题,并且复杂度为o(n)。

关键在于划分只一个部分,我们知道快速排序选择一个pivot对数组进行划分,左边小于pivot,右边大于等于pivot,所以我们计算左边小于pivot(加上pivot)的个数count总共有多少,如果等于k,正是我们所要的,如果大于k,说明第k小的数在左边,那就在左边进行我们的递归;否则,在右边,那么说明右边的第k-count小的数就是我们所要的,在右边进行我们的递归。


/* file: rand_select*//* 1、the same as the quicksort*//* 2、use a random algorithm to choose a pivot,  then split the Array into two subarrays.  the left elements are smaller than pivot,  the right elements are larger than pivot*//* 3、compare i with pivot'index to choose the  correct side of the Array.*//* 4、conquer to find the ith smallest element*/#include<stdio.h>#include <stdlib.h>/*=====================================  swap:swap two numbers a and b=======================================*/inline void swap(int* a,int* b){int tmp;tmp  = *a;*a   = *b;*b   = tmp;}/*=====================================  Partition:Partition the Array from startto end into two subarrays.Return the pivot of the elementArray[start]=======================================*/int Partition(int* Array, int start, int end){//choose Array[start] as the pivot element //divide the array into two subarrays.//left of the Array's elements <= Array[start]//right of the array's elements > Array[start]int pivot = start,j;for(j = start + 1; j <= end; j++)if(Array[j] <= Array[start]){pivot++;swap(&Array[pivot], &Array[j]);}swap(&Array[start], &Array[pivot]);return pivot;}/*=====================================  RandomPartition:using random algorithm.partition the  Array into two subarrays.Return the   pivot of the element Array[start] which  is already swaped=======================================*/int RandomPartition(int* Array, int start, int end){//generate the random index of the pivotint random_index = start + rand() % (end - start + 1);//swap the pivot with the random_index elementswap(&Array[start], &Array[random_index]);//now random_index element act as the start elementreturn Partition(Array,start,end);}/*=====================================  RandSelect:find the ith smallest element=======================================*/int RandSelect(int* Array, int start, int end, int i){int pivot, k;//this is the end of the conquerif(start == end) return Array[start];//use RandomPartition function to split the Arraypivot = RandomPartition(Array, start, end);k = pivot - start + 1;//conquerif(i == k) return Array[pivot];if(i < k)return RandSelect(Array, start, pivot - 1, i);elsereturn RandSelect(Array, pivot + 1, end, i - k);}void main(){int n, i, k, selected;printf("Please input the length of Array<0:exit>:\n");while(scanf("%d",&n),n){//create an arrays of length nint* Array = new int[n];//get the input integersprintf("Please input %d integers:\n",n);for(i = 0; i < n; i++)scanf("%d",&Array[i]);//get the kprintf("Please input <k>:");scanf("%d",&k);//use RandSelect algorithomselected = RandSelect(Array, 0, n-1, k);//print the kth smallest elementprintf("The %dth smallest element is %d:\n",k, selected);system("pause");system("cls");//delete the arraydelete[] Array;printf("Please input the length of Array<0:exit>:\n");}}


原创粉丝点击