手写基数排序算法

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基数排序(Radix sort)是一种非比较型整数排序算法,其基本思想为:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一个待排序整数序列,将其中每个整数看成由不同位构成(比如,个位十位百位千位...)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以先按个位的数值,将这些数分配到0~9的10个桶中,然后再按从0到9的顺序把这些数从10个桶中收集回来,这时这些数就已经按照个位排好序了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然后再按照10位上的数值,把这些数分配到10个桶中,分配完毕后再次收集回来,这时这些数就已经按照十位和个位排好序了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再按百位、千位依次进行上述过程,直到排序的位数到达数列中最大数的最高位,则排序结束。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由于计算机中字符、浮点等都是由整数来表示的,因此基数排序算法是一种普适性的算法,可以用于整数、字符、浮点数排序。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基数排序算法的核心过程,包括:","attrs":{}}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"计算出待排序数列的最大值 max","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"计算出最大值的最高位位数 div_cnt","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"分配内存,代表0~9的10个桶,用于存储数据","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"循环div_cnt 次,每次根据一个分位(个位,十位,百位...),将这些数据分配到桶中,然后再按桶的顺序将数据收集回来。循环结束后,数据就已经是排好序的了。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"释放内存。","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基数排序,用一个例子来图解说明:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"待排序数列:36, 341, 45, 8, 257","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"准备10个桶,存储从0到9的分位值:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/39/3952291d6fa863b49b6abe2792f35ae1.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先将每个整数,按个位上的值,分配到对应的桶中:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/26/26dd4153d6370898e1a2196d37ef85fa.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从桶中将数据收集回来,得到的数列为:341, 45, 36, 257, 8","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再将每个整数,按十分位上的值,分配到对应的桶中:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f7/f7d513e35f1df6a05f151bf878e86a20.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从桶中将数据收集回来:8,36, 341, 45, 257","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再将每个整数,按百分位上的值,分配到对应的桶中:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/44/44b44d05fe7c9480b71ad4df579cc3be.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从桶中将数据收集回来:8,36, 45, 257,341","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由于百分位是最大数的最高位,因此排序结束。最终的​排序结果是:8,36, 45, 257,341","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基数排序, 用C 语言实现的代码如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(ivec_t 是动态变长数组,存储integer 数据。类似c++中的vector,代码实现见后面)","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"void radix_sort(int* parr, int count) {\n // 1. compute maximum value\n int max = parr[0];\n for (int i = 1; i < count; i++) {\n if (parr[i] > max) {\n max = parr[i];\n }\n }\n\n // 2. computer div_cnt\n int div_cnt = 0;\n int max_temp = max;\n while (max_temp > 0) {\n max_temp /= 10;\n div_cnt++;\n }\n\n // 3. alloc memory for sorting\n ivec_t* pvecs = (ivec_t*)malloc(10 * sizeof(ivec_t));\n for (int i = 0; i < 10; i++) {\n ivec_init(pvecs + i, 8);\n }\n\n // 4. sort\n int divisor = 1;\n for (int k = 0; k < div_cnt; k++) {\n // clear memory\n for (int i = 0; i < 10; i++) {\n ivec_clear(pvecs + i);\n }\n\n // distribute to ivec\n for (int i = 0; i < count; i++) {\n int idx = (parr[i] / divisor) % 10;\n ivec_append(pvecs + idx, parr[i]);\n }\n divisor *= 10;\n\n // collect from ivec\n int idx = 0;\n for (int i = 0; i < 10; i++) {\n int* pbuf = ivec_buf(pvecs + i);\n int cnt = ivec_len(pvecs + i);\n for (int n = 0; n < cnt; n++) {\n parr[idx++] = pbuf[n];\n }\n }\n }\n\n // 5. free memory\n for (int i = 0; i < 10; i++) {\n ivec_destroy(pvecs + i);\n }\n free(pvecs);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上述代码中,使用了 ivec_t 这样的数据结构及相关函数,实现对桶的数据管理。ivec_t 的实现代码如下:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"typedef struct ivec_t {\n int cap;\n int len;\n int* pbuf;\n} ivec_t;\n\nint ivec_init(ivec_t* pvec, int cap);\nint ivec_append(ivec_t* pvec, int val);\nint ivec_len(ivec_t* pvec);\nint* ivec_buf(ivec_t* pvec);\nvoid ivec_clear(ivec_t* pvec);\nint ivec_destroy(ivec_t* pvec);\n\nint ivec_init(ivec_t* pvec, int cap) {\n pvec->len = 0;\n pvec->cap = cap;\n pvec->pbuf = (int*)malloc(cap * sizeof(int));\n return 0;\n}\n\nint ivec_append(ivec_t* pvec, int val) {\n if (pvec->len >= pvec->cap) { // need expand\n int new_cap = pvec->cap * 2;\n int* pnew_buf = realloc(pvec->pbuf, new_cap * sizeof(int));\n if (!pnew_buf) {\n return -1;\n }\n\n pvec->pbuf = pnew_buf;\n pvec->cap = new_cap;\n }\n\n pvec->pbuf[pvec->len++] = val;\n return 0;\n}\n\nint ivec_len(ivec_t* pvec) {\n return pvec->len;\n}\n\nint* ivec_buf(ivec_t* pvec) {\n return pvec->pbuf;\n}\n\nvoid ivec_clear(ivec_t* pvec) {\n pvec->len = 0;\n}\n\nint ivec_destroy(ivec_t* pvec) {\n free(pvec->pbuf);\n memset(pvec, 0, sizeof(*pvec));\n return 0;\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​我的微信号是 实力程序员,欢迎大家转发至朋友圈,分享给更多的朋友。","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章