排序算法

目录

调研对象

对比分析

详细功能调研

希尔排序

冒泡排序

选择排序

插入排序

快速排序

归并排序

堆排序

桶排序

基数排序

计数排序

二叉树排序


调研对象

·  冒泡排序(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");

}

https://www.cnblogs.com/mzct123/p/8288047.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值