菜鸟教程
Acwing
冒泡排序
void bubble_sort(T arr[], int len){
for(int i = 0; i < len - 1; i ++){
for(int j = 0; j < len - 1 - i; j ++){
if(arr[j] > arr[j + 1]){
swap(arr[j], arr[j + 1]);
}
}
}
}
选择排序
void selection_sort(vector<T>& arr){
for(int i = 0; i < arr.size() -1; i ++){
int min = i;
for(int j = i + 1; j < arr.size(); i ++){
if(arr[j] < min) min = j;
}
swap(arr[j], arr[min]);
}
}
插入排序
有直接插入排序和折半插入排序两种
void insertion_sort(int arr[], int len){
for(int i = 1; i < len; i++){
int key = arr[i];
int j = i - 1;
while((j >= 0) && (key < arr[j])){
arr[j + 1] = arr[j];
j --;
}
arr[j + 1] = key;
}
}
希尔排序
思想:设计一个增量序列,最后一次一定是1
每趟排序,把待排序记录分成若干子序列,分别插入排序
void shell_sort(T array[], int length){
int h = 1;
while(h < length / 3){
h = 3 * h + 1;
}
while(h >= 1){
for(int i = h; i < length; i++){
for(int j = i; j >= h && array[j] < array[j - h]; j -= h){
swap(array[j], array[j - h]);
}
}
h = h / 3;
}
}
归并排序
void merge_sort(int q[], int l, int r){
if(l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = 1, j = mid + 1;
while(i <= mid && j <= r)
if(q[i] <= q[j]) tmp[k ++] = q[i ++];
else tmp[k ++] = q[j ++];
while(i <= mid) tmp[k ++] = q[i ++];
while(j <= r) tmp[k ++] = q[j ++];
for(i = l, j = 0,i <= r; i++, j ++) q[i] = tmp[j];
}
快速排序
void quick_sort(int q[], int l, int r){
if(l >= r) return;
int i = l -1, j = r + 1, x = q[l + r >>1];
while(i < j){
do i ++; while(q[i] < x);
do j --; while(q[j] > x);
if(i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j+ 1, r);
}
堆排序
思想:大根堆
void HeadAdjust(int a[], int k, int len){
a[0] = a[k];
for(int i = 2 * k; i <= len; i *= 2){
if(i < len && a[i] < a[i + 1]) i ++;
if(a[0] >= a[i]) break;
else{
a[k] = a[i];
k = i;
}
}
a[k] = a[0];
}
void BuildHeap(int a[], int len){
for(int i = len / 2; i > 0; i --){
HeadAdjust(a, i , len);
}
}
void HeapSort(int a[], int len){
BuildHeap(a, len);
for(int i = len; i > 1; i --){
swap(a[i], a[1]);
HeadAdjust(a, 1, i - 1);
}
}
计数排序
思想:每个桶只存储一个单一的值
朴素版 根据最大值开辟存储空间且不稳定
void count_sort(int a[], int n){
int minval = a[0], maxval = a[0];
for(int i = 0; i < n; i++){
minval = min(minval, a[i]);
maxval = max(maxval, a[i]);
}
int cnt[maxval + 1] = {0};
for(int i = 0; i < n; i ++) cnt[a[i]] ++;
for(int i = minval, k = 0; i <= maxval; i++){
while(cnt[i] != 0){
data[k ++] = i;
cnt[i] --;
}
}
}
优化版 根据实际的数组长度开辟空间且不稳定
void count_sort(int a[], int n){
int minval = a[0], maxval = a[0];
for(int i = 0; i < n; i++){
minval = min(minval, a[i]);
maxval = max(maxval, a[i]);
}
int d = maxval - minval + 1;
int cnt[d] = {0};
for(int i = 0; i < n; i ++) cnt[a[i] - minval] ++;
for(int i = 0, k = 0; i <= maxval - minval; i++){
while(cnt[i] != 0){
data[k ++] = i + minval;
cnt[i] --;
}
}
}
二次优化版 稳定排序
void count_sort(int a[], int n){
int minval = a[0], maxval = a[0];
for(int i = 0; i < n; i ++){
minval = min(minval, a[i]);
maxval = max(maxval, a[i]);
}
int d = maxval - minval + 1;
int cnt[d] = {0};
for(int i = 0; i < n; i ++) cnt[a[i] - minval] ++;
int sum = 0;
for(int i = 0; i < d; i ++){
sum += cnt[i];
cnt[i] = sum;
}
int sortArray[d];
for(int i = n - 1; i >= 0; i --){
sortArray[cnt[a[i] - minval] - 1] = a[i];
cnt[a[i] - minval] --;
}
for(int i = 0, k = 0; i < d; i ++){
data[k ++] = sortArray[i];
}
}
桶排序
空间换时间
思想:把一个范围的数值分到一个桶
void bucket_sort(int a[], int n){
int minval = a[0], maxval = a[0];
for(int i = 0; i < n; i++){
minval = min(minval, a[i]);
maxval = max(maxval, a[i]);
}
int bnum = 10;
int m = (maxval - minval) / bnum + 1;
vector< vector<int>> bucket(m);
for(int i = 0; i < n; i++) bucket[(a[i] - minval ) / bnum].push_back(a[i]);
for(int i = 0; i < m; i++) sort(bucket.begin(), bucket.end());
for(int i =0, k = 0; i < m; i++){
for(int j = 0; j < bucket[i].size();j ++){
data[k ++] = bucket[i][j];
}
}
}
基数排序
思想:把每一位的数字分到一个桶中
int maxbit(int data[], int n)
{
int maxData = data[0];
for (int i = 1; i < n; ++i)
{
if (maxData < data[i])
maxData = data[i];
}
int d = 1;
int p = 10;
while (maxData >= p)
{
maxData /= 10;
++d;
}
return d;
}
void radixsort(int data[], int n)
{
int d = maxbit(data, n);
int *tmp = new int[n];
int *count = new int[10];
int i, j, k;
int radix = 1;
for(i = 1; i <= d; i++)
{
for(j = 0; j < 10; j++)
count[j] = 0;
for(j = 0; j < n; j++)
{
k = (data[j] / radix) % 10;
count[k]++;
}
for(j = 1; j < 10; j++)
count[j] = count[j - 1] + count[j];
for(j = n - 1; j >= 0; j--)
{
k = (data[j] / radix) % 10;
tmp[count[k] - 1] = data[j];
count[k]--;
}
for(j = 0; j < n; j++)
data[j] = tmp[j];
radix = radix * 10;
}
delete []tmp;
delete []count;
}
位图排序
思想:用对应的32bit位对应十进制的0-31个数
位移转换:
1.确定十进制数在数组中下标的位置 idx = b[i] / 32;
2.求十进制数对应0-31中的数 x = b[i] % 32;
3.利用位移操作 b[idx] += (1 << 1);
@Test
public void bitmap_sort()
{
int[] a = new int[]{1, 6, 22, 4, 7, 2, 8, 30, 25, 5, 67, 80, 54, 90, 142};
int[] b = new int[1 + 142/ 32];
for (int k : a) {
int idx = k / 32;
int x = k % 32;
b[idx] += 1 << x;
}
for(int j = 0; j < b.length; j++){
for(int i = 0; i < 32; i ++){
if((b[j] >> i & 1) == 1) System.out.print(32 * j + i + " ");
}
}
}
快速幂
m^k%p
思想:把k分成 2^0 + 2^1 + …
int qmi(int m, int k, int p){
int res = 1 % p;
while(k){
if(k&1) res = res * m % p;
m = m * m % p;
k >> 1;
}
return res;
}
|