---
title: 'Sorting HW2'
---
# **Sorting HW2**
###### tags: `sorting` `python`
Q1. 傳統的 Quick sort 是 1 個 Pivot、2 個 Partition,若改為 2 個 Pivot、3 個 Partition,演算過程要如何調整?演算速度是否會變快?
---
Q2. 如果數值 1~1000,共 1000000000 個整數,如果要排序,該如何設計?
---
**Algo**
首先假設數列無法全部放入 memory,因此無法全部讀入再排序。同理,輸出也一樣需要分段輸出,依排序寫入到同一個 file。由於數列內容為純數值,且 K(位數 = 3)<< N(資料個數 = $10^9$),所以適合 Counting Sort。演算法步驟:
1. 先產生一組隨機 1~1000,共 1000000000 個整數的檔案作為測資,每個數之間以「,」分開。
2. 宣告一個 array(Count),大小為 1001 用來記錄 1~1000 數字個別出現多少次。
3. 宣告一個 String(num_str)用來記錄目前讀到的數字的字串。
4. 每次只讀取一個字元,while 讀取直到讀到空字元停止。
5. 如果讀到非「,」字元則將該字元加到當前讀到的數字字串(num_str)中,代表讀取的是同一個數字。
6. 如果讀到「,」字元,代表目前記錄的數字字串是要排序的數字。將 num_str 轉成整數,並在對應的 Count 位置 +1。
7. 讀完之後,從小到大依據 Count 紀錄的個數字出現次數寫入 output file,一次只寫入一個數字。
8. 寫一個 check_answer.py 執行步驟 3. 4. 5. 6.,不同的是每次只比較當前數字是否大於等於上一次的數字,並在最後統計個數是否等於 $10^9$。
**Code**
Q2_SortingTesting.c
```c=
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define RANGE 1000
#define SAMEPLE_TIMES 1000000000
void randomArray(int arraySize, FILE* output_file) {
int i;
int x;
x = rand() % arraySize;
fprintf(output_file, "%d", x);
for(i = 1 ; i < SAMEPLE_TIMES ; i++) {
x = rand() % arraySize + 1;
fprintf(output_file, ",%d", x);
}
}
int main(int argc, char *argv[]) {
int i;
int numArray[RANGE];
const char* file_name = "SortingTesting3.txt";
FILE* output_file = fopen(file_name, "a+");
srand(time(NULL));
randomArray(RANGE, output_file);
fclose(output_file);
return 0;
}
```
Q2_Sort.py
```python=
INPUT_FILE_PATH = "./SortingTesting_Q2_test.txt"
OUTPUT_FILE_PATH = "./SortedData_Q2_test.txt"
if __name__ == "__main__":
count = [0] * 1001
in_f = open(input_file_path, "r")
readChar = in_f.read(1)
num_str = "" + readChar
while(readChar != ''):
readChar = in_f.read(1)
if(readChar == ","):
count[int(num_str)] += 1
num_str = ""
elif (readChar == ''):
break
else:
num_str += readChar
count[int(num_str)] += 1
in_f.close()
out_f = open(output_file_path, "a+")
for i in range(1001):
if count[i] > 0:
out_f.write(str(i))
count[i] -= 1
break
for i in range(1001):
while count[i] > 0:
out_f.write("," + str(i))
count[i] -= 1
out_f.close()
```
Q2_check_answer.py
```python=
SORTEDDATA_FILE_PATH = "./SortedData_Q2_test.txt"
NUMBERS = 1000000
if __name__ == "__main__":
in_f = open(SORTEDDATA_FILE_PATH, "r")
l = 0
lastNum = 0
readChar = in_f.read(1)
numStr = "" + readChar
while(readChar != ''):
readChar = in_f.read(1)
if(readChar == ","):
l += 1
if int(numStr) < lastNum:
print("FAIL AT " + l + "TH NUMBER")
break
if l > (NUMBERS):
print("TOO MANY NUMBERS")
break
lastNum = int(numStr)
numStr = ""
elif (readChar == ''):
break
else:
numStr += readChar
l += 1
if int(numStr) < lastNum:
print("FAIL AT " + l + "TH NUMBER")
elif l < (NUMBERS):
print("LOST NUMBERS")
elif l > (NUMBERS):
print("TOO MANY NUMBERS")
else:
print("SUCCESS")
in_f.close()
```
Q3. 如果全球統一了,身分證規格相同,都是一個字母加上 12 碼 0~9 的數字,要排序,該如何設計?
---
情境假設 :
固態硬碟1TB以上 (75億筆字串約110GB)
記憶體32G (1億筆以物件儲存約7G)
執行步驟 :
1.原檔案約110GB。
2.考量到記憶體使用,批次讀取檔案每次一億筆。
3.以一億筆資料為一個Chunk使用radix sort 排序。
4.排序完寫入暫存檔案,並釋放記憶體。
5.重複步驟2~5,直到所有資料被排序,並產生n個chunk檔案。
6.對n個chunk檔案使用merge sort並寫入最後的檔案。
```python=
import pandas as pd
import numpy as np
import random
import sys
import os
id_list=[]
for i in range (1500):
id_list.append(i)
random.shuffle(id_list)
file_object = open('sample.csv', 'a')
for i in range(len(id_list)):
file_object.write(str(id_list[i]))
file_object.close()
def read_in_chunks(filePath, chunk_size=10*1):
file_object = open(filePath)
while True:
chunk_data = file_object.read(chunk_size)
if not chunk_data:
break
yield chunk_data
print(chunk_data)
```
Q4. 呈 2,如果數量不變,但數值改成長度不固定的字串(長度至少 5),要排序,該如何設計?
---