排序2

本博客的代碼的思想和圖片參考:好大學慕課浙江大學陳越老師、何欽銘老師的《數據結構》node

 

 

排序2git

 

1 快速排序

 

1.1 算法思想

 

快速排序的主要思想就是分而治之。選擇一個主元,而後把原來的集合分爲比主元小和比主元大兩個子集合,而後遞歸的解決左邊,遞歸的解決右邊。咱們使用一幅圖片來進行說明算法

 

 

 

 

 

 

 

 

 

 

 

 

 

下面是快速排序的僞代碼描述數組

 

void Quicksort( ElementType A[], int N )數據結構

 

{ app

 

if ( N < 2 ) return;dom

 

pivot = A[]中選一個主元;ide

 

S = { A[] \ pivot } 分紅2個獨立子集:函數

 

A1={ aS | a  pivot } oop

 

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:


103 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
相關文章
相關標籤/搜索