目录
调研对象
· 冒泡排序(Bubble Sort)
· 插入排序(Insertion Sort)
· 希尔排序(Shell Sort)
· 选择排序(Selection Sort)
· 快速排序(Quick Sort)
· 归并排序(Merge Sort)
· 堆排序(Heap Sort)
· 计数排序(Counting Sort)
· 桶排序(Bucket Sort)
· 基数排序(Radix Sort)
· 二叉树排序
对比分析
详细功能调研
希尔排序
希尔排序是先分组,然后再插入排序的一种算法。所以是希尔发明的分组插入排序算法。
void shell_sort( int* data, int length)
{
int gap=0;
int i=0, j=0;
for( gap=length/2; gap>=1;gap/=2)
{
for( i=gap; i<length;i++) {
for( j=i; j-gap >= 0; j-=gap) {
if(data[j-gap]>data[j])
{
swap( data[j-gap], data[j]);
}
}
}
}
}
冒泡排序
冒泡排序是想象10个轻重不一的气泡球放置在水中,依次从水底最后一个开始向上顺序比较,最轻的在第一趟冒出到第一位。第一趟比9次,第二趟比8次,直到比1次,每次都从水底开始, 每次都能确定一个最轻的上浮到排好的位置。
void bubble_sort(int* data, int length) {
for(int i=0; i < length; i++) {
for(int j=length-1; j > i; j--) {
if(data[j] < data[j-1]) {
swap(data[j], data[j-1]);
}
}
}
}
选择排序
选择排序是每次遍历都把第一个元素当成最小的元素,和剩余的其他元素比较。其他元素小就交换值。第一次是length-1次比较,最后一次是比较一次。
void select_sort(int* data, int length) {
for(int i=0; i<length-1; i++) {
int min = i;
for(int j = i+1; j < length; j++) {
if(data[j] < data[min]) {
swap(data[j], data[min]);
}
}
}
}
插入排序
插入排序是类似10张扑克牌,先拿出一张,然后每次拿出一张和已拿出的比较,并排好顺序。 这样每次循环都是有序的。 总共拿出9次。 每次排都是从后往前遍历一遍。
void insert_sort(int* data, int length) {
for(int i=1; i<length; i++) {
for(int j = i; j >0; j--) {
if(data[j-1] > data[j]) {
swap(data[j-1], data[j]);
}
}
}
}
快速排序
快速排序是右左依次填坑取中分组递归排序法,每次都能把排序的中间值给比较出来。
void quick_sort2(int* data, int l,int r) {
int i = l;
int j = r;
int x = data[i];
while(i<j) {
while(i<j && data[j] >= x) {
j--;
}
if(i<j) {
data[i] = data[j];
i++;
}
while(i<j && data[i] < x) {
i++;
}
if(i<j) {
data[j] = data[i];
j--;
}
data[i] = x;
quick_sort(data, l, i-1);
quick_sort(data, i+1, r);
}
}
归并排序
归并排序是一种从中间分成两组,分别对两个有序数组进行合并排序
可参考https://zhuanlan.zhihu.com/p/124356219
void merge(int data[], int tempArray[], int nBegin, int nEnd, int middle) {
int index1 = nBegin;
int index2 = middle+1;
int i = 0;
for(i=nBegin; index1 <= middle && index2 <= nEnd; i++) {
if(data[index1] < data[index2]) {
tempArray[i] = data[index1++];
} else {
tempArray[i] = data[index2++];
}
}
while(index1 <= middle) {
tempArray[i++] = data[index1++];
}
while(index2 <= nEnd) {\
tempArray[i++] = data[index2++];
}
for(int j=nBegin; j<=nEnd; j++) {
data[j] = tempArray[j];
}
}
void merge_sort(int data[], int tempArray[], int nBegin, int nEnd) {
if(nBegin < nEnd) {
int middle = (nBegin + nEnd)/2;
merge_sort(data, tempArray, nBegin, middle);
merge_sort(data, tempArray, middle+1, nEnd);
merge(data, tempArray, nBegin, nEnd, middle);
}
}
堆排序
堆排序是把数组映射成完全二叉树,第一步建立大顶堆,第二部每次取出堆顶最大值,放置在数组尾部倒置
第一个非叶子节点索引 length/2-1
void test_heap_sort() {
int data[10] = {33,22,16,8,322,87,23,77,4,256};
int length = 10;
// 构建大顶堆
for(int i=length/2-1; i>=0; i--) {
heap_sort(data, i, length);
}
// 调整堆结构,交换堆顶元素和末尾元素
for(int j=length-1; j>=1; j--)
{
swap(data[0], data[j]);
heap_sort(data, 0, j);
}
printf("堆排序从小到大排列: \n");
for(int i=0; i<10; i++){
cout << data[i] << " " <<flush;
}
printf("\n");
}
void heap_sort(int* data, int i, int length) {
int temp = data[i];
for(int k=2*i+1; k<length; k=2*k+1) {
if(k+1 < length && data[k] < data[k+1]) {
k++;
}
if(data[k] > temp) {
swap(data[i], data[k]);
i = k;
} else {
break;
}
}
}
可参考https://www.cnblogs.com/chengxiao/p/6129630.html
桶排序
桶排序是一种数字值间隔比较大的排序的算法。
void bucket_sort(int* data, int length) {
int max = data[0];
int min = data[0];
for(int i=0; i<length; i++) {
max = (max < data[i] ? data[i]:max);
min = (min > data[i] ? data[i]:min);
}
// 每个桶是个集合
int bucketNum = (max-min)/length + 1; // 保证至少一个桶
vector<vector<int>*> bucketArray(bucketNum);
for(int i=0; i<bucketNum; i++) {
bucketArray[i] = new vector<int>();
}
// 所有元素放入桶中
for(int i=0; i<length; i++) {
int num = (data[i] - min)/length;
bucketArray[num]->push_back(data[i]);
}
// 每个桶内进行排序
for(int i=0; i<bucketNum; i++) {
sort(bucketArray[i]->begin(), bucketArray[i]->end());
}
// 输出所有排序的元素
int index = 0;
for(int i=0; i<bucketNum; i++) {
for(int j=0; j<bucketArray[i]->size(); j++) {
data[index++] = bucketArray[i]->at(j);
}
}
for(int i=0; i<bucketNum; i++) {
delete bucketArray[i];
}
}
可参考https://www.cnblogs.com/protected/p/6603536.html
基数排序
基数排序是一种依赖10进制(0~9)的位数进行排序的算法,先按各位数从小到大排放入桶中,循环到最高位,即排好顺序 (求取最大位,在从个位到最高位过程中,装入桶中,从桶中取出拼接数组)
int getMaxBitSize(int* data, int length) {
int maxSize = 0;
for(int i=0; i<length; i++) {
int tempSize = 1;
int tempValue = data[i];
while((tempValue = tempValue/10) != 0) {
tempSize++;
}
maxSize = (maxSize < tempSize ? tempSize : maxSize);
}
return maxSize;
}
void radix_sort(int* data, int length) {
int keyBit[10][10] ={0};
int bitNum[10] = {0};
int n=1;
int sizeNum = getMaxBitSize(data,length);
for(int i=0; i<sizeNum; n*=10,i++) {
// 装入桶中
for(int j=0; j<length; j++) {
int flag = (data[j]/n)%10;
keyBit[flag][bitNum[flag]] = data[j];
bitNum[flag]++;
}
// 桶中数重新拼接成数组
int index = 0;
for(int j=0; j<10; j++) {
int flagNum = bitNum[j];
for(int k=0; k<flagNum; k++) {
data[index++] = keyBit[j][k];
}
bitNum[j] = 0;
}
}
}
计数排序
计数排序是数字间排列比较密集时采用,取出最小最大值,申请全量的数组,然后记录每个源数组值的出现的次数。根据出现的次数,重新组合出新的排序过的数组
void test_count_sort() {
int data[10] = {2,7,9,5,4,11,13,17,6,8};
int* result = count_sort(data, 10);
printf("计数排序从小到大:\n");
for(int i=0; i<10; i++){
cout << result[i] << " " <<flush;
}
printf("\n");
}
int* count_sort(int* data, int length) {
int max = data[0];
int min = data[0];
for(int i=0; i<length; i++) {
max = (max < data[i] ? data[i]:max);
min = (min > data[i] ? data[i]:min);
}
// 找出每个数字出现的次数
int* help = new int[max-min+1];
memset(help, 0, sizeof(int) * (max-min+1));
for(int j=0; j<length; j++) {
help[(data[j] - min)]++;
}
// 计算每个数字应该在排序数组中的位置
for(int k=1; k < (max-min+1); k++) {
help[k] = help[k-1] + help[k];
}
// 根据help记录,从新返回新的数组
int* result = new int[length];
memset(result, 0, sizeof(int)*length);
for(int m = 0; m<length; m++) {
int pos = --help[data[m]-min];
result[pos] = data[m];
}
return result;
}
可参考https://www.cnblogs.com/protected/p/6603536.html
二叉树排序
可参
typedef int KEY_VALUE;
#define BSTREE_ENTRY(name, type)\
struct name {\
type* left;\
type* right;\
}
struct bstree_node {
KEY_VALUE data;
BSTREE_ENTRY(,bstree_node) bst;
};
struct bstree {
struct bstree_node* root;
};
struct bstree_node* bstree_create_node(KEY_VALUE data) {
struct bstree_node* node = (struct bstree_node*)malloc(sizeof(struct bstree_node));
if(node == NULL) {
assert(0);
}
node->data = data;
node->bst.left = node->bst.right = NULL;
return node;
}
int bstree_insert(struct bstree* T, int key) {
assert(T != NULL);
if(T->root == NULL) {
T->root = bstree_create_node(key);
return 0;
}
struct bstree_node* node = T->root;
struct bstree_node* tmp = T->root;
while(node != NULL) {
tmp = node;
if(key < node->data) {
node = node->bst.left;
} else {
node = node->bst.right;
}
}
if(key < tmp->data) {
tmp->bst.left = bstree_create_node(key);
} else {
tmp->bst.right = bstree_create_node(key);
}
return 0;
}
int bstree_travelsal(struct bstree_node* node) {
if(node == NULL) return -1;
bstree_travelsal(node->bst.left);
printf("%d ", node->data);
bstree_travelsal(node->bst.right);
return 0;
}
void test_bstree_travelsal() {
int nArray1[] = {33,22,55,8,5,48,23,77,4,128};
bstree tree = {0};
for(int i=0; i<10; i++) {
bstree_insert(&tree, nArray1[i]);
}
printf("二叉树排序°:êo\n");
bstree_travelsal(tree.root);
printf("\n");
}