排序2

本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

 

 

排序2

 

1 快速排序

 

1.1 算法思想

 

快速排序的主要思想就是分而治之。选择一个主元,然后把原来的集合分为比主元小和比主元大两个子集合,然后递归的解决左边,递归的解决右边。我们使用一幅图片来进行说明

 

 

 

 

 

 

 

 

 

 

 

 

 

下面是快速排序的伪代码描述

 

void Quicksort( ElementType A[], int N )

 

{

 

if ( N < 2 ) return;

 

pivot = A[]中选一个主元;

 

S = { A[] \ pivot } 分成2个独立子集:

 

A1={ aS | a  pivot }

 

A2={ aS | a  pivot };

 

A[] =

 

Quicksort(A1,N1)U

 

pivot}U

 

Quicksort(A2,N2);

 

}

 

1.2 快速排序的性能分析

 

因为快速排序是递归进行的,递归算法的好处体现在每次可以递归的解决规模差不多的子问题。如果主元选的不好,让子集大小很悬殊,那么快速排序就快不起来了。下面是使用一幅图片来说明如果主元选取的不好,那么就会很囧。

 



 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

可以看出,如果主元选的不好,那么快速排序的时间复杂度为O(N^2),很糟糕

 

1.3 常见的选择主元的方法

 

1.随机取 pivot?rand()函数不便宜啊!

 

2.取头、中、尾的中位数

 

例如 8123的中位数就是8

 

下面给出中位数法的伪代码描述

 

ElementType Median3( ElementType A[], int Left, int Right )

 

{

 

int Center = ( Left + Right ) / 2;

 

if ( A[ Left ] > A[ Center ] )

 

Swap( &A[ Left ], &A[ Center ] );

 

if ( A[ Left ] > A[ Right ] )

 

Swap( &A[ Left ], &A[ Right ] );

 

if ( A[ Center ] > A[ Right ] )

 

Swap( &A[ Center ], &A[ Right ] );

 

/* A[ Left ] <= A[ Center ] <= A[ Right ] */

 

Swap( &A[ Center ], &A[ Right-1 ] ); /* pivot藏到右边 */

 

/* 只需要考虑 A[ Left+1 ] ... A[ Right–2 ] */

 

return A[ Right-1 ]; /* 返回 pivot */

 

}

 

1.4 子集划分算法

 

使用一幅图片来说明

 


 

 

 

 

 

 

 

 

 

如果有元素正好等于pivot怎么办?

 

1.停下来交换?

 

1.不理它,继续移动指针?

 

举一个极端的例子,如果,如果一个数组全是和主元相等,如果使用停下来交换,就会做无用的交换,如果 不理它,继续移动指针,那么i会一直移动到大于j,此时我们的主元就会在端点,那么所造成的影响就是时间复杂度为O(N^2)

 

所以我们选择 停下来交换

 



 

1.5快速排序的问题

 

1.用递归......

 

对小规模的数据(例如N不到100)可能还不如插入排序快

 



 

2.解决方案

 

当递归的数据规模充分小,则停止递归,直接调用简单排序(例如插入排序)

 

在程序中定义一个Cutoff的阈值 —— 课后去实践一下,比较不同的Cutoff对效率的影响

 



 

1.6快速排序的测试结果

 

 

 



 



 

 

 

 

 

阀值都取100的情况下

 


 

 

 

 

1.7 结果分析

 

对于不同的阀值,发现效率差距并不是很大。但是选择不同pivot,差距很大。从测试结果看

 

中位数效果最好,随机数次之,使用第一个元素作为pivot效果最差。所以今后尽量使用中位数方法。

1.8 快速排序代码

 

  1 /*
  2  * quickSort.c
  3  *
  4  *  Created on: 2017年5月20日
  5  *      Author: ygh
  6  */
  7 
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #define  MAX_LENGTH 100000
 11 typedef int elementType;
 12 
 13 /*
 14  * Swap two integer number value
 15  */
 16 void swap(elementType *a, elementType *b) {
 17     int temp = *b;
 18     *b = *a;
 19     *a = temp;
 20 }
 21 
 22 /*
 23  * Print the array to console
 24  * @param a A integer array need to sort
 25  * @param n The length of the array
 26  */
 27 void printArray(int a[], int n) {
 28     int i;
 29     for (i = 0; i < n; i++) {
 30         if (i == n - 1) {
 31             printf("%d", a[i]);
 32         } else {
 33             printf("%d ", a[i]);
 34         }
 35     }
 36     printf("\n");
 37 }
 38 
 39 /*
 40  * Get input data from command
 41  */
 42 void getInputData(elementType *a, int n) {
 43     int i;
 44     elementType x;
 45     for (i = 0; i < n; i++) {
 46         scanf("%d", &x);
 47         a[i] = x;
 48     }
 49 }
 50 
 51 /*
 52  * Implement insertion sort.
 53  *@param a A <code>elementType</code> array need to sort
 54  *@param n The length of the array
 55  */
 56 void insertion_sort(elementType a[], int n) {
 57     int i, j;
 58     elementType temp;
 59     for (i = 1; i < n; i++) {
 60         temp = a[i];
 61         for (j = i; j > 0 && a[j - 1] > temp; j--) {
 62             a[j] = a[j - 1];
 63         }
 64         a[j] = temp;
 65     }
 66 
 67 }
 68 
 69 /*
 70  *Get the pivot by get the median amount three number
 71  */
 72 elementType getPivotByMedian3(elementType a[], int left, int right) {
 73     int center = (left + right) / 2;
 74     /*
 75      * Let a[left]<= a[center] <= a[right]
 76      */
 77     if (a[left] > a[center]) {
 78         swap(&a[left], &a[center]);
 79     }
 80 
 81     if (a[left] > a[right]) {
 82         swap(&a[left], &a[right]);
 83     }
 84 
 85     if (a[center] > a[right]) {
 86         swap(&a[center], &a[right]);
 87     }
 88 
 89     /*
 90      * We has known the a[right] greater than a[center]
 91      * so we swap the a[center] and a[right-1],so we just
 92      * consider from a[left+1] to a[right-2] when we divide sub-set
 93      */
 94     swap(&a[center], &a[right - 1]);
 95     return a[right - 1];
 96 
 97 }
 98 
 99 elementType getPivotByRandom(elementType a[], int left, int right) {
100     int index = rand() % (right - left + 1) + left;
101     return index;
102 }
103 
104 /*
105  * Implement quick sort,we get the pivot by the middle of three numbers
106  * @param a A <code>elementType</code> array need to sort
107  * @param left The starting index of sub-set
108  * @param right The finishing index of sub-set
109  * @param A cutoff to determine how many numbers rest we will
110  * use the insertion sort.
111  */
112 void qSort(elementType a[], int left, int right, int cutoff) {
113     int low, high;
114     elementType pivot;
115     if (cutoff <= right - left) {
116         pivot = getPivotByMedian3(a, left, right);
117         low = left;
118         high = right - 1;
119         while (1) {
120             while (a[++low] < pivot)
121                 ;
122             while (a[--high] > pivot)
123                 ;
124             if (low < high) {
125                 swap(&a[low], &a[high]);
126             } else {
127                 break;
128             }
129         }
130         swap(&a[low], &a[right - 1]);
131         qSort(a, left, low - 1, cutoff);
132         qSort(a, low + 1, right, cutoff);
133 
134     } else {
135         insertion_sort(a + left, right - left + 1);
136     }
137 }
138 
139 /*
140  * Implement quick sort,we get the pivot by the middle of three numbers
141  * @param a A <code>elementType</code> array need to sort
142  * @param left The starting index of sub-set
143  * @param right The finishing index of sub-set
144  * @param A cutoff to determine how many numbers rest we will
145  * use the insertion sort.
146  */
147 void qSortByRandom(elementType a[], int left, int right, int cutoff) {
148     int low, high, index;
149     elementType pivot;
150     if (cutoff <= right - left) {
151         index = getPivotByRandom(a, left, right);
152         swap(&a[left], &a[index]);
153         pivot = a[left];
154         low = left;
155         high = right;
156         while (low < high) {
157             while (low < high && a[high] >= pivot) {
158                 high--;
159             }
160             a[low] = a[high];
161             while (low < high && a[low] <= pivot) {
162                 low++;
163             }
164             a[high] = a[low];
165         }
166         a[low] = pivot;
167         qSortByRandom(a, left, low - 1, cutoff);
168         qSortByRandom(a, low + 1, right, cutoff);
169     } else {
170         insertion_sort(a + left, right - left + 1);
171     }
172 }
173 
174 /*
175  * Implement quick sort,we get the pivot by the middle of three numbers
176  * @param a A <code>elementType</code> array need to sort
177  * @param left The starting index of sub-set
178  * @param right The finishing index of sub-set
179  * @param A cutoff to determine how many numbers rest we will
180  * use the insertion sort.
181  */
182 void qSortByFirstNum(elementType a[], int left, int right, int cutoff) {
183     int low, high;
184     elementType pivot;
185     if (cutoff <= right - left) {
186         pivot = a[left];
187         low = left;
188         high = right;
189         while (low < high) {
190             while (low < high && a[high] >= pivot) {
191                 high--;
192             }
193             a[low] = a[high];
194             while (low < high && a[low] <= pivot) {
195                 low++;
196             }
197             a[high] = a[low];
198         }
199         a[low] = pivot;
200         qSortByFirstNum(a, left, low - 1, cutoff);
201         qSortByFirstNum(a, low + 1, right, cutoff);
202     } else {
203         insertion_sort(a + left, right - left + 1);
204     }
205 }
206 
207 /*
208  * Implement sort unitized interface
209  * @param a A <code>elementType</code> array need to sort
210  * @param n The length of the array
211  */
212 void quickSort(elementType a[], int n) {
213 //    qSort(a, 0, n - 1, 100);
214 //    qSortByRandom(a, 0, n - 1, 100);
215     qSortByFirstNum(a, 0, n - 1, 2);
216 }
217 
218 
219 
220 int main() {
221     int a[MAX_LENGTH];
222     int n;
223     scanf("%d", &n);
224     getInputData(a, n);
225     quickSort(a, n);
226     printArray(a, n);
227     return 0;
228 }
quickSort

 

 

2 表排序

2.1概述

在我们之前学过的排序中,我们都是使用交换两个元素的位置来进行排序。可是如果现在的元素不是两个简单的数字,而是2G的视频,如果进行交换位置的排序,那么就要计算元素移动的时间。那么我们然后对这些元素进排序呢。



2.2 算法思想

下面有一组数据,里面的数据我们可以抽象是结构体存储。每个数据按照key去排序。但是结构体里面不仅仅有key,每个结构体还有2G的视频内容。那我们如何进行排序。例如下图:



 

 

 

 

 

 

那么如何在不进行移动元素的情况下,对数据按key进排序。我们在为数据增加一行指针数组,叫做表(table),来记录正确顺序的A的角标。初始化指针数组的值和A的角标对应。然后我们安装普通排序的方法(插入排序)对指针数组进排序。如,按照插入排序,第一趟比较fd的大小 ,d<f,则把table0角标元素往后面摞一位,然后在table0角标放入1值。代表指向a[1].keytable1角标存放0,代表指向a[0].key。然后下面按照插入排序进行对table的元素进排序。

下面使用一幅图片来说明:



 

 

 

2.3 物理排序

上面我们已经在逻辑上把数据排好序了,如果只需顺序输出,那么我只需要做A[table[0]],A[table[1]]… a[table[n-1]]即可。但是如果我们需要把把数据进行排序,让其逻辑上进行有序,那应该怎么做。



首先我们有一个定理:N个数字的排列由若干个独立的环组成

我们来看一下我们最终排序的结果:



 

 

 

 

 

 

由于进行元素的交换,则产生环路。位置和初始状态没有发生改变的独自成环。下面我们需要根据环来对物理数据进行排序。

首先建立一个临时的数据存储单元temp,用来存储临时的变量。我们从A[0]开始。temp=f,通过table[0]找到A[3],A[0]=A[3],并更新table[0]=0;在通过A[3]table[3]找到A[1],A[3]=A[1],更新table[3]=3……

如何判断环结束table[i]==i

2.4 时间复杂度分析

最好情况:一开始有序,那么就不需要进行交换

我们知道,每一个环需要开辟一个temp数组,如果一个环中有T个元素,需要移动T+1,多了两次temp的移进和移出。

那么最坏的情况是有N/2个环,每个环有2个元素,每个环需要移动3次。总共需移动(3N)/2

T=O(mN).m为每个元素移动的时间,当元素的移动时间不能忽略时,就必须加上m



3 基数排序

3.1 桶排序

我们首先举一个例子:

 

 

 

 

 

 

 

 

 

3.2基数排序的算法思想

 

 

3.3 基数排序思想的应用

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

表排序的源代码

  1 /*
  2  * tableSort.c
  3  *
  4  *  Created on: 2017年5月22日
  5  *      Author: ygh
  6  */
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #define MAX_LENGTH 100
 10 
 11 typedef int contentType;
 12 
 13 typedef struct node element;
 14 typedef struct node {
 15     char key;
 16     contentType content;
 17 } data[MAX_LENGTH];
 18 
 19 typedef struct node1 *ptrTable;
 20 typedef struct node1 {
 21     data d;
 22     int table[MAX_LENGTH];
 23 };
 24 
 25 /*
 26  * Create a empty table to store data
 27  * @param n The length of the table
 28  * @return ptrTable A point of structure of the table
 29  */
 30 ptrTable createEmptyTable(int n) {
 31     ptrTable table = (ptrTable) malloc(sizeof(struct node1));
 32     int i;
 33     for (i = 0; i < n; i++) {
 34         table->table[i] = i;
 35     }
 36     return table;
 37 }
 38 
 39 /*
 40  * Insert a data to table
 41  * @param table A point of structure of the table
 42  * @param index The index of the element inserted
 43  * @param key The key of the element inserted
 44  * @param content The content of the element inserted
 45  */
 46 void insertData(ptrTable table, int index, char key, contentType content) {
 47     table->d[index].content = content;
 48     table->d[index].key = key;
 49 }
 50 
 51 /*
 52  * Implement table sort.
 53  * Algorithms thoughts:
 54  * 1.Because the data in <code>data</code> is too large,So we don't swap them
 55  * 2.We use a table to record the data position,at the first time,the table's value is
 56  *     equal the index in the <code>data</code>
 57  * 3. we sort data by key and record the sorted position by the table
 58  * 4.When we need to access the table sorted,we just access data[table[i]]
 59  *
 60  * @param table A point of structure of the table
 61  * @param n The length of the table
 62  */
 63 void tableSort(ptrTable table, int n) {
 64     int i, j;
 65     char key;
 66     int t;
 67     for (i = 1; i < n; i++) {
 68         key = table->d[i].key;
 69         t = table->table[i];
 70         for (j = i; j > 0 && table->d[table->table[j - 1]].key > key; j--) {
 71             table->table[j] = table->table[j - 1];
 72         }
 73         table->table[j] = t;
 74     }
 75 }
 76 
 77 /*
 78  * Implement the data physical sort according the table
 79  * @param table A point of structure of the table
 80  * @param n The length of the table
 81  *
 82  */
 83 void physicalSort(ptrTable table, int n) {
 84     int i, j;
 85     int t;
 86     element temp;
 87     for (i = 0; i < n; i++) {
 88         if (table->table[i] != i) {
 89             temp = table->d[i];
 90             t = table->table[i];
 91             table->d[i] = table->d[t];
 92             table->table[i] = i;
 93             j = t;
 94             while (t != i) {
 95                 t = table->table[j];
 96                 if (t == i) {
 97                     break;
 98                 }
 99                 table->d[j] = table->d[t];
100                 table->table[j] = j;
101                 j = t;
102             }
103             table->d[j] = temp;
104             table->table[j] = j;
105         } else {
106             continue;
107         }
108     }
109 }
110 
111 /*
112  * Print the table's content to console
113  * @param table A point of structure of the table
114  * @param n The length of the table
115  */
116 void toStringTale(ptrTable table, int n) {
117     int i;
118     for (i = 0; i < n; i++) {
119         printf("key:%c,content:%d\n", table->d[table->table[i]].key,
120                 table->d[table->table[i]].content);
121     }
122 }
123 
124 int main() {
125     char arr[] = "fdcagbhe";
126     int i;
127     int n = 8;
128     ptrTable table = createEmptyTable(n);
129     for (i = 0; i < n; i++) {
130         insertData(table, i, arr[i], i);
131     }
132     tableSort(table, n);
133     //toStringTale(table, n);
134     physicalSort(table, n);
135     toStringTale(table, n);
136     return 0;
137 }
TableSort

表排序的测试结果:

1 key:a,content:3
2 key:b,content:5
3 key:c,content:2
4 key:d,content:1
5 key:e,content:7
6 key:f,content:0
7 key:g,content:4
8 key:h,content:6
TableSortTestResult

 

基数排序LSD

  1 /*
  2  * radixSortLSD.c
  3  * Implement radix sort of Least Significant Digit
  4  *
  5  *  Created on: 2017年5月23日
  6  *      Author: ygh
  7  */
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 
 11 #define  MAX_LENGTH 10000
 12 
 13 /*
 14  *The quantity of the the keys of element
 15  *For example 0-9999 have four keys
 16  */
 17 #define MAX_DIGIT 6
 18 /*
 19  *The quantity of the bucket.In this case ,we sort integer number
 20  *So the buckets is from 0 to 9
 21  */
 22 #define RADIX 10
 23 
 24 #define BEGIN_DIGIT 0
 25 
 26 /*
 27  * The type of the element type
 28  */
 29 typedef int elementType;
 30 
 31 /*
 32  * Define a data structure for bucket node
 33  */
 34 typedef struct node *ptrToNode;
 35 typedef struct node {
 36     /*
 37      * The element type the bucket node store
 38      */
 39     elementType key;
 40     /*
 41      * A next point to point next element
 42      */
 43     ptrToNode next;
 44 
 45 };
 46 
 47 /*
 48  * Define a data structure for bucket head that
 49  * store the head point and rear point for the elements
 50  */
 51 typedef struct headNode {
 52     ptrToNode head, rear;
 53 };
 54 
 55 /*
 56  * Define a array of headNode to store the all buckets
 57  */
 58 typedef struct headNode bucket[RADIX];
 59 
 60 /*
 61  * Get the digit by the current number and current needed digit
 62  * @param x The current number
 63  * @param d The current digit
 64  * @return The digit needed
 65  */
 66 int getDigit(elementType x, int d) {
 67     int i;
 68     int di;
 69     for (i = 0; i < d; i++) {
 70         di = x % RADIX;
 71         x = x / RADIX;
 72     }
 73     return di;
 74 }
 75 
 76 void LSDRadixSort(elementType a[], int n) {
 77     int d, di, i;
 78     /*
 79      * Define a bucket array to store all buckets
 80      */
 81     bucket b;
 82 
 83     /*
 84      * Define three node point
 85      * @param temp Store temporary node
 86      * @param p A node point will be used when search
 87      * @param list A node point to build elements list and recovery
 88      * elements from finished sort
 89      */
 90     ptrToNode temp, p, list;
 91 
 92     /*
 93      * Initialize each bucket head and rear into NULL
 94      */
 95     for (i = BEGIN_DIGIT; i < RADIX; i++) {
 96         b[i].head = b[i].rear = NULL;
 97     }
 98 
 99     /*
100      * Change array elements into list elements,but it is DESC
101      */
102     for (i = 0; i < n; i++) {
103         temp = (ptrToNode) malloc(sizeof(struct node));
104         temp->key = a[i];
105         temp->next = list;
106         list = temp;
107     }
108 
109     /*
110      * Do radix sort
111      */
112     for (d = 1; d <= MAX_DIGIT; d++) {
113         p = list;
114         while (p) {
115             di = getDigit(p->key, d);
116             if (di < 0) {
117                 di = di * (-1);
118             }
119             /*
120              * Delete this element from the list
121              */
122             temp = p;
123             p = p->next;
124             temp->next = NULL;
125             if (b[di].head == NULL) {
126                 b[di].head = b[di].rear = temp;
127             } else {
128                 b[di].rear->next = temp;
129                 b[di].rear = temp;
130             }
131         }
132 
133         /*
134          * Recover the elements has been deal with,using
135          * the list to point the head
136          */
137         list = NULL;
138         for (di = RADIX - 1; di >= BEGIN_DIGIT; di--) {
139             if (b[di].head) {
140                 b[di].rear->next = list;
141                 list = b[di].head;
142                 /*
143                  * Clear the head and rear
144                  */
145                 b[di].rear = b[di].head = NULL;
146             }
147         }
148     }
149 
150     /*
151      * Put sorted list data to array
152      */
153     for (i = 0; i < n; i++) {
154         temp = list;
155         list = list->next;
156         a[i] = temp->key;
157         free(temp);
158     }
159 
160 }
161 
162 /*
163  * Print the array to console
164  * @param a A integer array need to sort
165  * @param n The length of the array
166  */
167 void printArray(int a[], int n) {
168     int i;
169     for (i = 0; i < n; i++) {
170         if (i == n - 1) {
171             printf("%d", a[i]);
172         } else {
173             printf("%d ", a[i]);
174         }
175     }
176     printf("\n");
177 }
178 
179 /*
180  * Get input data from command
181  */
182 void getInputData(elementType *a, int n) {
183     int i;
184     elementType x;
185     for (i = 0; i < n; i++) {
186         scanf("%d", &x);
187         a[i] = x;
188     }
189 }
190 
191 /*
192  * Separate a array into positive array and negative array
193  * @param a A array store the positive number or negative number
194  * @param n The length of the a
195  * @param pL The length of the positive array
196  * @param pL The length of the negative array
197  */
198 void separate(elementType *a, int n, int *pL, int *nL,
199         elementType positiveArr[], elementType negativeArr[]) {
200     int i;
201     for (i = 0; i < n; i++) {
202         if (a[i] < 0) {
203             negativeArr[(*nL)++] = a[i];
204         } else {
205             positiveArr[(*pL)++] = a[i];
206         }
207     }
208 }
209 
210 /*
211  * Implement radix sort
212  */
213 void radixSort(elementType a[], int n) {
214     int positiveArr[MAX_LENGTH];
215     int negativeArr[MAX_LENGTH];
216     int pL = 0, nL = 0, i, j;
217     separate(a, n, &pL, &nL, positiveArr, negativeArr);
218     LSDRadixSort(positiveArr, pL);
219     LSDRadixSort(negativeArr, nL);
220     i = nL - 1;
221     j = 0;
222     while (i >= 0) {
223         a[j] = negativeArr[i];
224         i--;
225         j++;
226     }
227     i = 0;
228     while (i < pL) {
229         a[j] = positiveArr[i];
230         i++;
231         j++;
232     }
233 
234 }
235 
236 int main() {
237     elementType a[MAX_LENGTH];
238     int n;
239     scanf("%d", &n);
240     getInputData(a, n);
241     radixSort(a, n);
242     printArray(a, n);
243     return 0;
244 }
RadixSortLSD

基数排序MSD

/*
 * radixSortMSD.c
 *Implement radix sort(Most Significant Digit)
 *  Created on: 2017年5月24日
 *      Author: ygh
 */
#include <stdio.h>
#include <stdlib.h>

#define MAX_LENGTH 100000
#define RADIX 10
#define MAX_DIGIT 3
#define BEGIN_DIGIT 0

/*
 * Define element type the array or list store
 */
typedef int elementType;

/*
 * Define a list to store elememts from array
 */
typedef struct node *ptrToNode;
typedef struct node {
    elementType key;
    ptrToNode next;
};

/*
 * Define a bucket to point the each bucket list head and rear
 */
typedef struct headNode {
    ptrToNode head, rear;
};

/*
 *Define a bucket array to store all buckets
 */
typedef struct headNode bucket[RADIX];

/*
 * Get the current number digit by current digit needed
 * @param x The number current need to sort
 * @param d The digit current need to get
 * @return A current digit of this number
 */
int getDigit(elementType x, int d) {
    int i;
    int de;
    for (i = 0; i < d; i++) {
        de = x % RADIX;
        x = x / RADIX;
    }
    return de;
}

/*
 * Implement radix sort by MSD,we will recursive to implement it
 */
void radixSortMSD(elementType a[], int left, int right, int d) {
    int di, i, j;
    /*
     * Define three point of the list
     * @param p The point is used for searching
     * @param temp The point is used for temporary store
     * @param list The point is used for store all elements
     */
    ptrToNode p, temp, list = NULL;
    /*
     * Define a bucket array for all buckets
     */
    bucket b;

    /*
     * recursive end conditional
     */
    if (d == 0) {
        return;
    }
    /*
     * Initialize all bucket,let head and rear get NULL
     */
    for (i = BEGIN_DIGIT; i < RADIX; i++) {
        b[i].head = b[i].rear = NULL;
    }

    /*
     * Change array storing into list storing,it make the data
     * easily to be deal with
     */
    list = NULL;
    for (i = left; i <= right; i++) {
        temp = (ptrToNode) malloc(sizeof(struct node));
        temp->key = a[i];
        temp->next = list;
        list = temp;
    }

    p = list;
    /*
     * Get digit from current number and deal with them
     */
    while (p) {
        di = getDigit(p->key, d);
        temp = p;
        p = p->next;
        temp->next = NULL;
        if (b[di].head == NULL) {
            b[di].rear = temp;
            b[di].head=temp;
        } else {
            temp->next = b[di].head;
            b[di].head = temp;
        }

    }

    /*
     * recover elements from bucket
     */
    i = j = left;
    for (di = 0; di < RADIX; di++) {
        if (b[di].head) {
            p = b[di].head;
            while (p) {
                temp = p;
                p = p->next;
                a[j++] = temp->key;
                free(temp);
            }
            /*
             *recursive caller this method
             */
            radixSortMSD(a, i, j - 1, d - 1);
            i = j;
        }
    }
}

/*
 * Implement radix sort
 */
void radixSort(elementType a[], int n) {
    radixSortMSD(a, 0, n - 1, MAX_DIGIT);
}

/*
 * Print the array to console
 * @param a A integer array need to sort
 * @param n The length of the array
 */
void printArray(int a[], int n) {
    int i;
    for (i = 0; i < n; i++) {
        if (i == n - 1) {
            printf("%d", a[i]);
        } else {
            printf("%d ", a[i]);
        }
    }
    printf("\n");
}

/*
 * Get input data from command
 */
void getInputData(elementType *a, int n) {
    int i;
    elementType x;
    for (i = 0; i < n; i++) {
        scanf("%d", &x);
        a[i] = x;
    }
}

int main() {
    elementType a[MAX_LENGTH];
    int n;
    scanf("%d", &n);
    getInputData(a, n);
    radixSort(a, n);
    printArray(a, n);
    printf("just test");
    return 0;
}
RadixSortMSD

 

练习题:


10-排序4 统计工龄   (20分)

给定公司NNN名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。
输入格式:

输入首先给出正整数NNN(≤105\le 10^5≤10​5​​),即员工总人数;随后给出NNN个整数,即每个员工的工龄,范围在[0, 50]。
输出格式:

按工龄的递增顺序输出每个工龄的员工个数,格式为:“工龄:人数”。每项占一行。如果人数为0则不输出该项。
输入样例:

8
10 2 0 5 7 2 5 2

输出样例:

0:1
2:3
5:2
7:1
10:1

    时间限制:400ms
    内存限制:64MB
    代码长度限制:16kB
    判题程序:系统默认
    作者:陈越
    单位:浙江大学

题目判定
解题程序
编译器:*
程序代码:*
提交

我使用了归并排序为基础,下面是代码的实现

  1 /*
  2  * countAge.c
  3  *
  4  *  Created on: 2017年5月24日
  5  *      Author: ygh
  6  */
  7 
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #define  MAX_LENGTH 100000
 11 
 12 typedef int elementType;
 13 
 14 /*
 15  * Swap two integer number value
 16  */
 17 void swap(elementType *a, elementType *b) {
 18     int temp = *b;
 19     *b = *a;
 20     *a = temp;
 21 }
 22 
 23 /*
 24  * Merge sub-sequence to original array.
 25  * @param a original <code>elementType</code> array to store the elements
 26  * @param tmpA temporary  <code>elementType</code> array to store the temporary elements
 27  * @param l The start index of left sub-sequence
 28  * @param r The start index of left sub-sequence
 29  * @param rightEnd The end index of left sub-sequence
 30  */
 31 void merge(elementType a[], elementType tmpA[], int l, int r, int rightEnd) {
 32     /*
 33      * lefeEnd is the r-1,the sub-sequence is adjacent
 34      */
 35     int leftEnd = r - 1;
 36     /*
 37      * tmp is the counter of the <code>tmpA</code>
 38      * we should let <code>tmpA</code> index corresponding original array
 39      */
 40     int tmp = l;
 41     /*
 42      * Record the quantity of the all elements
 43      */
 44     int numElements = rightEnd - l + 1;
 45     int i;
 46     while (l <= leftEnd && r <= rightEnd) {
 47         if (a[l] <= a[r]) {
 48             tmpA[tmp++] = a[l++];
 49         } else {
 50             tmpA[tmp++] = a[r++];
 51         }
 52     }
 53     while (l <= leftEnd) {
 54         tmpA[tmp++] = a[l++];
 55     }
 56     while (r <= rightEnd) {
 57         tmpA[tmp++] = a[r++];
 58     }
 59 
 60     /*
 61      * Put <code>tmpA</code> elements into the original array
 62      */
 63     for (i = 0; i < numElements; i++, rightEnd--) {
 64         a[rightEnd] = tmpA[rightEnd];
 65     }
 66 }
 67 
 68 /*
 69  * Implement the merge sort
 70  * @param a original <code>elementType</code> array to store the elements
 71  * @param tmpA temporary  <code>elementType</code> array to store the temporary elements
 72  * @param l The start index of the array which need to sort
 73  * @param rightEnd The end index of the array which need to sort
 74  */
 75 void mergetSortRecursive(elementType a[], elementType tmpA[], int l,
 76         int rightEnd) {
 77     int center;
 78     if (l < rightEnd) {
 79         center = (l + rightEnd) / 2;
 80         mergetSortRecursive(a, tmpA, l, center);
 81         mergetSortRecursive(a, tmpA, center + 1, rightEnd);
 82         merge(a, tmpA, l, center + 1, rightEnd);
 83     }
 84 }
 85 
 86 /*
 87  * Implement merge sort
 88  * @param a A integer array need to sort
 89  * @param n The length of the array
 90  */
 91 void merger_sortRecursive(elementType a[], int n) {
 92     elementType *tmpA;
 93     tmpA = malloc(n * sizeof(elementType));
 94     if (tmpA != NULL) {
 95         mergetSortRecursive(a, tmpA, 0, n - 1);
 96         free(tmpA);
 97     } else {
 98         printf("no enough space to apply for temporary array");
 99     }
100 }
101 
102 /*
103  *merge ordered sub-sequence
104  * @param a original <code>elementType</code> array to store the elements
105  * @param tmpA temporary  <code>elementType</code> array to store the temporary elements
106  * @param n The length of the a
107  * @param the ordered current sub-sequence length
108  */
109 void mergerPass(elementType a[], elementType tmpA[], int n, int lenth) {
110     int i, j;
111     /*
112      * The loop will stop when meet the last two ordered sub-sequence
113      * The rest may be two sub-sequence of one sub-sequence
114      */
115     for (i = 0; i <= n - 2 * lenth; i += lenth * 2) {
116         merge(a, tmpA, i, i + lenth, i + 2 * lenth - 1);
117     }
118     /*
119      *If the rest of is two sub-sequence
120      */
121     if (i + lenth < n) {
122         merge(a, tmpA, i, i + lenth, n - 1);
123     } else {
124         for (j = i; j < n; j++)
125             tmpA[j] = a[j];
126     }
127 }
128 
129 /*
130  * Use loop method to implement the merge sort
131  * @param a A integer array need to sort
132  * @param n The length of the array
133  */
134 void merger_SortLoop(elementType a[], int n) {
135     int length;
136     elementType *tmpA;
137     length = 1;
138     tmpA = malloc(n * sizeof(elementType));
139     if (tmpA != NULL) {
140         while (length < n) {
141             /*
142              * merge ordered sub-sequence into <code>tmpA</code>
143              */
144             mergerPass(a, tmpA, n, length);
145             length *= 2;
146             /*
147              * merge ordered sub-sequence from <code>tmpA</code> into <code>a</code>
148              */
149             mergerPass(tmpA, a, n, length);
150             length *= 2;
151         }
152         free(tmpA);
153     } else {
154         printf("no enough to apply for temporary array");
155     }
156 }
157 
158 /*
159  * Print the array to console
160  * @param a A integer array need to sort
161  * @param n The length of the array
162  */
163 void printArray(int a[], int n) {
164     int i;
165     for (i = 0; i < n; i++) {
166         if (i == n - 1) {
167             printf("%d", a[i]);
168         } else {
169             printf("%d ", a[i]);
170         }
171     }
172     printf("\n");
173 }
174 
175 /*
176  * Get input data from command
177  */
178 void getInputData(elementType *a, int n) {
179     int i;
180     elementType x;
181     for (i = 0; i < n; i++) {
182         scanf("%d", &x);
183         a[i] = x;
184     }
185 }
186 
187 /*
188  * Count age and print them to console
189  */
190 void countAge(elementType a[], int n) {
191     int i;
192     int key = a[0];
193     int counter = 1;
194     for (i = 1; i < n; i++) {
195         if (a[i] == key) {
196             counter++;
197         } else {
198             printf("%d:%d\n",key,counter);
199             key = a[i];
200             counter=1;
201         }
202     }
203     printf("%d:%d\n",key,counter);
204 }
205 
206 int main() {
207     int a[MAX_LENGTH];
208     int n;
209     scanf("%d", &n);
210     getInputData(a, n);
211     merger_SortLoop(a, n);
212     countAge(a, n);
213     return 0;
214 }
CountAge

 

 

 

4 练习



4.1 Sort with Swap(0, i)

Given any permutation of the numbers {0, 1, 2,..., N−1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}

Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.

Input Specification:

Each input file contains one test case, which gives a positive N (≤10​5​​) followed by a permutation sequence of {0, 1, ..., N−1}. All the numbers in a line are separated by a space.

Output Specification:

For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

Sample Input:

10
3 5 7 2 6 4 9 0 8 1

Sample Output:

9
  • 时间限制:400ms

  • 内存限制:64MB

  • 代码长度限制:16kB

  • 判题程序:系统默认

  • 作者:陈越

  • 单位:浙江大学

4.2 算法思想

这道题目要求我们和零交换来实现排序,那么我们联想到之前的表排序,如何对下表实现物理排序,那么需要在每个环中进行位置的交换。在环中进行位置交换的时候,我们会先使用一个临时的空间去存放第一个需要交换的元素,然后让第一个元素有一个空位,然后把下一个元素移动到第一个元素的位置。直到环中的最后一个元素,把临时空间中的元素移动到最后一个元素的位置。根据此算法思想,我们可以衍生此题的解法。我们把每次移动的空闲位置区域看做是0,然后每次移动元素时,就相当和0进行交换。如果有的环不包括0,怎么办?我们可以把0换到环里,然后进行移动。

 

4.3 环的分类

 

 

4.4 程序的实现

我们知道0-N个元素有序排列应该这样

下标

0

1

2

3

4

5

6

7

8

9

A[]

0

1

2

3

4

5

6

7

8

9



但是现在题目所给的序列为这样

下标

0

1

2

3

4

5

6

7

8

9

A[]

3

5

7

2

6

4

9

0

8

1



我们需要建立如下一个数组T[],来记录当前元素存储的位置,例如A[0]应该存放0元素,但是我们不能遍历一遍A[]去查找0元素,这样太慢了。我们在插入0时就应该记录0所在的位置。例如插入0的时候,i7,我们需要记录T[A[i]]=i。这样我们就可以很快的通过A[0]=0=A[T[0]]

下面我们构造T[]数组



下标

0

1

2

3

4

5

6

7

8

9

T[]

7

9

3

0

5

1

4

2

8

6

这样我们可以建立一个环了。

 

 

下面是代码:代码可以通过PTA所有的测试点

  1 /*
  2  * SortwithSwap.c
  3  *
  4  *  Created on: 2017年5月25日
  5  *      Author: ygh
  6  */
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 
 10 #define MAX_LENGTH 100000
 11 
 12 typedef int elementType;
 13 /*
 14  * Define a data structure to store data
 15  */
 16 typedef struct dataNode *ptrToData;
 17 typedef struct dataNode {
 18     elementType a[MAX_LENGTH];
 19     int table[MAX_LENGTH];
 20 };
 21 
 22 /*
 23  * Create empty array point
 24  */
 25 ptrToData createEmptyData() {
 26     ptrToData data = (ptrToData) malloc(sizeof(struct dataNode));
 27     return data;
 28 }
 29 
 30 /*
 31  * Insert element to data and record the index
 32  * @param data A point to point the data
 33  * @param n The length of the arrays
 34  */
 35 void insertElement(ptrToData data, int n) {
 36     elementType x;
 37     int i;
 38     for (i = 0; i < n; i++) {
 39         scanf("%d", &x);
 40         data->a[i] = x;
 41         data->table[x] = i;
 42     }
 43 }
 44 
 45 /*
 46  *Calculate the swap times.when we access next element by
 47  *circle, we let the counter increase one. If the circle contain zero,counter decrease one
 48  *otherwise counter increase one.
 49  * @param data A point to point the data
 50  * @param n The length of the arrays
 51  * @param m The counter of the multiple circle
 52  * @param s The counter of the single circle
 53  */
 54 int calculateSwapTimes(ptrToData data, int n) {
 55     /*
 56      * @param key  The index to record the next element by circle
 57      * @param j The index the current element
 58      */
 59     int i,key,j;
 60     /*
 61      * record the all swap
 62      */
 63     int counter=0;
 64     for (i = 0; i < n; i++) {
 65         if(i==data->table[i]){
 66             continue;
 67         }else{
 68             key = data->table[i];
 69             counter++;
 70             data->table[i]=i;
 71             j=key;
 72             while(key!=i){
 73                 key=data->table[j];
 74                 counter++;
 75                 data->table[j]=j;
 76                 j = key;
 77             }
 78             if(i==0){
 79                 counter--;
 80             }else{
 81                 counter++;
 82             }
 83         }
 84     }
 85     return counter;
 86 }
 87 
 88 void toString(ptrToData data, int n) {
 89     int i;
 90     for (i = 0; i < n; i++) {
 91         printf("%d ", data->a[data->table[i]]);
 92     }
 93 }
 94 
 95 int main() {
 96     ptrToData data = createEmptyData();
 97     int n,count;
 98     scanf("%d", &n);
 99     insertElement(data, n);
100     count = calculateSwapTimes(data, n);
101     printf("%d",count);
102     return 0;
103 }
SortWithSwap

 

posted @ 2017-05-20 20:53  浪漫逆风  阅读(322)  评论(0编辑  收藏  举报