快速排序及拓展

  1. 快排的递归版本和非递归版本。
  2. 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。(29)
  3. 输入n个数,找出其中最小的k个数。(30)

1、思路:

  递归版本:首先随机选定分割数,对数组中小于该分割数的放在左侧,大于该分割数的放在右侧。递归处理左侧和右侧的数字。

《快速排序及拓展》
《快速排序及拓展》
QuickSort

 1  #include <stdio.h>
 2  #include <stdlib.h>
 3  #include <exception>
 4  
 5  void PrintArray(int* data, int length)
 6  {
 7      for (int i = 0; i < length; i++)
 8          printf("%d ", data[i]);
 9      printf("\n");
10  }
11  
12  void Swap(int* a, int* b)
13  {
14       int temp;
15       temp = *a;
16       *a = *b;
17       *b = temp;
18  }
19  
20  int Random(int min, int max)
21  {
22      int random = rand() % (max - min + 1) + min;
23      return random;
24  }
25  
26  int Partition(int* data, int start, int end)
27  {
28      int index = Random(start, end);
29      Swap(&data[index], &data[end]);
30      int small = start;
31      for (index = start; index < end; index++)
32      {
33          if (data[index] < data[end])
34          {
35              Swap(&data[small], &data[index]);
36              small++;
37          }
38      }
39      Swap(&data[small], &data[end]);
40      return small;
41  }
42  
43  void QuickSort(int* data, int start, int end)
44  {
45      if (start == end)
46          return;
47      int index = Partition(data, start, end);
48      if (index > start)
49          QuickSort(data, start, index - 1);
50      if (index < end)
51          QuickSort(data, index + 1, end);
52  }
53  
54  int main()
55  {
56      int test[7] = {23, 13, 49, 6, 31, 19, 28};
57      PrintArray(test, 7);
58      QuickSort(test, 7, 0, 6);
59      PrintArray(test, 7);
60  }

  非递归版本:用数组和下标来模拟栈的操作。

 1 #include <stdlib.h>
 2 #include <stdio.h>
 3 #define SIZE 1000
 4 
 5 typedef struct _stackNode
 6 {
 7     int low;
 8     int high;
 9 }stackNode;
10 
11 void PrintArray(int data[], int len)
12 {
13     for (int i = 0; i < len; i++)
14         printf("%d ", data[i]);
15     printf("\n");
16 }
17 
18 void Swap(int* a, int* b)
19 {
20     int temp;
21     temp = *a;
22     *a = *b;
23     *b = temp;
24 }
25 
26 int Random(int min, int max)
27 {
28     int r = rand() % (max - min + 1) + min;
29     return r;
30 }
31 
32 int Partition(int* data, int start, int end)
33 {
34     int index = Random(start, end);
35     Swap(&data[index], &data[end]);
36     int small = start;
37     for (index = start; index < end; index++)
38     {
39         if (data[index] < data[end])
40         {
41             Swap(&data[small], &data[index]);
42             small++;
43         }
44     }
45     Swap(&data[small], &data[end]);
46     return small;
47 }
48 
49 void quickSortNoneRecursive(int data[], int len)
50 {
51     int low, high, mid, top;
52     stackNode* st;
53     if ((st = (stackNode*)malloc(sizeof(stackNode) * SIZE)) == NULL)
54     {
55         printf("malloc fail!\n");
56         exit(0);
57     }
58     top = 0;
59     st[top].low = 0;
60     st[top].high = len - 1;
61 
62     while (top >= 0)
63     {
64         low = st[top].low;
65         high = st[top].high;
66         top--;
67         if (low < high)
68         {
69             mid = Partition(data, low, high);
70             if (low < mid)
71             {
72                 top++;
73                 st[top].low = low;
74                 st[top].high = mid - 1;
75             }
76             if (high > mid)
77             {
78                 top++;
79                 st[top].low = mid + 1;
80                 st[top].high = high;
81             }
82         }
83     }
84     free(st);
85 }
86 
87 int main()
88 {
89     int *data = (int*)malloc(sizeof(int) * SIZE);
90     for (int i = 0; i < SIZE; i++)
91         data[i] = rand() % SIZE;
92     PrintArray(data, 50);
93     quickSortNoneRecursive(data, SIZE);
94     PrintArray(data, 50);
95     return 0;
96 }

2、思路:

  因为一个数字的出现超过一半,所以他一定会出现在数组的中间。则用快速选择的方法,当找到中间位置即是该数。

《快速排序及拓展》
《快速排序及拓展》

 1  int MoreThanHalfNum_1(int* numbers, int length)
 2  {
 3       assert(numbers && length >= 0);
 4       int middle = length >> 1;
 5       int start = 0;
 6       int end = length - 1;
 7       int index = Partition(numbers, length, start, end);
 8       
 9       while (index != middle)
10       {
11           if (index > middle)
12           {
13               end = index - 1;
14               index = Partition(numbers, length, start, end);
15           }
16           else
17           {
18               start = index + 1;
19               index = Partition(numbers, length, start, end);
20           }
21       }
22  
23       int result = numbers[middle];
24       return result;
25  }

MoreThanHalfNum

3、思路:

  基于数组的第k个数来做调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边。但是最小的k个数字是没有排序的,另外也会更改原数组的位置。而且该算法要求所有n个数都要一次性放入内存,这对海量数据不合适。

《快速排序及拓展》
《快速排序及拓展》
GetLeastNumbers

 1 void GetLeastNumbers_Solution1(int* input, int n, int* output, int k)
 2 {
 3     if(input == NULL || output == NULL || k > n || n <= 0 || k <= 0)
 4         return;
 5 
 6     int start = 0;
 7     int end = n - 1;
 8     int index = Partition(input, n, start, end);
 9     while(index != k - 1)
10     {
11         if(index > k - 1)
12         {
13             end = index - 1;
14             index = Partition(input, n, start, end);
15         }
16         else
17         {
18             start = index + 1;
19             index = Partition(input, n, start, end);
20         }
21     }
22 
23     for(int i = 0; i < k; ++i)
24         output[i] = input[i];
25 }

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/wangpengjie/archive/2013/03/27/2984556.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞