reference
http://blog.csdn.net/acm_1361677193/article/details/48206603
思想/例子
【冒泡】一种交换排序1,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。http://blog.csdn.net/lemon_tree12138/article/details/50591859
【鸡尾酒 双向冒泡】
【插入】 常见的插入排序有插入排序(Insertion Sort),希尔排序(Shell Sort),二叉查找树排序(Tree Sort),图书馆排序(Library Sort),Patience排序(Patience Sort)
void SelectSort(int *a, int len)
{
for (int i=0; i<len-1; i++)
{
int k = i;
int key = a[i];
for (int j=i+1; j<len; j++)
{
if (a[j]<key)
{
k = j;
key = a[j];
}
}
if (k!=i)
swap(a[i], a[k]);
}
}
//直接插入排序:将一个记录插入到已经排好序的有序表中,得到新的有序表
【归并】
#include <iostream>
using namespace std;
/*归并过程--将两个有序数组合并成一个有序数组*/
void merge(int array[],int tempArray[],int left,int right,int middle)
{
int index1=left;
int index2=middle+1;
for(int i=left;(index1<=middle)&&(index2<=right);i++)
{
if(array[index1]<array[index2])
tempArray[i]=array[index1++];
else
tempArray[i]=array[index2++];
}
while(index1<=middle)
tempArray[i++]=array[index1++];
while(index2<=right)
tempArray[i++]=array[index2++];
for(i=left;i<=right;i++)
array[i]=tempArray[i];
}
/*两路归并排序--array[]为待排数组,tempArray[]为临时数组,left和right分别是数组两端*/
void mergeSort(int array[],int tempArray[],int left,int right)
{
if(left<right)
{
int middle=(left+right)/2;
mergeSort(array,tempArray,left,middle);
mergeSort(array,tempArray,middle+1,right);
merge(array,tempArray,left,right,middle);
}
}
int main()
{
int array[8]={6,8,7,3,1,2,5,4};
int tempArray[8];
mergeSort(array,tempArray,0,7);
for(int i=0;i<8;i++)
cout<<array[i]<<" ";
cout<<endl;
return 0;
}
【桶】
#include <iostream>
using namespace std;
/*归并过程--将两个有序数组合并成一个有序数组*/
void merge(int array[],int tempArray[],int left,int right,int middle)
{
int index1=left;
int index2=middle+1;
for(int i=left;(index1<=middle)&&(index2<=right);i++)
{
if(array[index1]<array[index2])
tempArray[i]=array[index1++];
else
tempArray[i]=array[index2++];
}
while(index1<=middle)
tempArray[i++]=array[index1++];
while(index2<=right)
tempArray[i++]=array[index2++];
for(i=left;i<=right;i++)
array[i]=tempArray[i];
}
/*两路归并排序--array[]为待排数组,tempArray[]为临时数组,left和right分别是数组两端*/
void mergeSort(int array[],int tempArray[],int left,int right)
{
if(left<right)
{
int middle=(left+right)/2;
mergeSort(array,tempArray,left,middle);
mergeSort(array,tempArray,middle+1,right);
merge(array,tempArray,left,right,middle);
}
}
int main()
{
int array[8]={6,8,7,3,1,2,5,4};
int tempArray[8];
mergeSort(array,tempArray,0,7);
for(int i=0;i<8;i++)
cout<<array[i]<<" ";
cout<<endl;
return 0;
}
【基数】
/*
* Get the spcific digit of given number.
* For example, number 234,
* the 0st digit is 4,
* the 1st digit is 3,
* the 2nd digit is 2,
* the 3th digit is 0.
*/
int GetNDigit(int nNumber, int nIdx)
{
for (int i = nIdx; i > 0; i--) {
nNumber /= 10;
}
return nNumber % 10;
}
/*
* Counting Sort the given array according to specific digit.
* array: 待排序数组.
* nLength: 待排序数组长度
* nIdxDigit: 排序要依据的位. 0为最低位,高位依次加1.
* nK: *nIdxDigit位上可能出现的最大数字(对10进制数排序则nK=9).
*/
void CountingSort_SpecificDigit(int array[], size_t nLength, int nIdxDigit, int nK=9)
{
if (NULL == array || 0 == nLength || 0 == nK)
return;
int *digitNum = new int[nLength];
memset(digitNum, 0, sizeof(int)*nLength);
int *count = new int[nK+1];
memset(count, 0, sizeof(int)*(nK+1));
int *arrayResult = new int[nLength];
memset(arrayResult, 0, sizeof(int)*nLength);
// 数组digitNum[],保存每个元素指定位上的数字,作为排序依据
for (int idx = 0; idx<nLength; idx++)
digitNum[idx] = GetNDigit(array[idx], nIdxDigit);
// 先计数,count[idx]为值等于idx的元素的个数
for (int idx = 0; idx<nLength; idx++)
count[digitNum[idx]]++;
// 再累加,count[idx]为小于等于idx的元素的个数
for (int idx = 1; idx<nK+1; idx++)
count[idx] = count[idx] + count[idx-1];
// 从后向前循环(保证排序稳定), 根据指定位的数字大小
// 将array[idx]排在所有小于等于array[idx]的数(共count[digitNum[idx]]个)的后面
for (int idx=nLength-1; idx>=0; idx--)
{
arrayResult[count[digitNum[idx]]-1] = array[idx];
count[digitNum[idx]]--;
}
// 把排序结果写回原数组
memcpy(array, arrayResult, sizeof(int)*nLength);
delete [] digitNum;
delete [] count;
delete [] arrayResult;
}
/*
* 基数排序
* array: 待排序数组
* nLength: 待排序数组元素个数
* nDigit: 所有元素的最大位数
*/
void RadixSort(int array[], size_t nLength, int nDigit)
{
// 从最低位到最高位,依次调用计数排序
for (int idx=0; idx<=nDigit; idx++) {
CountingSort_SpecificDigit(array, nLength, idx);
}
}
【二叉树】
#pragma once
#include<iostream>using namespace std;
//树节点定义,包含父节点指针(便于回溯前驱与后继)
typedef struct Node {
int data;
struct Node *leftchild;
struct Node *rightchild;
struct Node *parent;
}Node_t;
/*
二叉排序树类定义
*/
class BSearchTree{
public:
BSearchTree(void);
~BSearchTree(void);
inline Node_t* getRoot() const { return this->root;}
void createBSTree(int *dataset, int size); //建立二叉排序树
bool insertNode(Node_t **root, int value); //插入新节点,需要传入二级指针(改变根指针的值)
void inorderTraverse(Node_t *root) const; //中序遍历
void visitMiddleOrder() const; //对上一函数继续封装
Node_t* searchNode(Node_t *root,int value) const; //按值查找
void searchByValue(int value) const; //对上一函数继续封装
//最大与最小代码对称
void getMax(Node_t *root) const; //获取最大值
void getMin(Node_t *root) const; //获取最小值
//前驱与后继代码对称
void getPredecessor(Node_t *node); //获取节点前驱
void getSuccessor(Node_t *node); //获取节点后继
int getHeight(Node_t *root) const; //返回树高
private:
Node_t *root; //根节点
};
成员函数的实现:
#include "BSearchTree.h"
BSearchTree::BSearchTree(void)
{ root = NULL;
}
BSearchTree::~BSearchTree(void)
{
//to do sth
}
//建立二叉排序树(导入数组内元素,逐一插入)void BSearchTree:: createBSTree(int *dataset, int size) {
for ( int i=0; i<size; i++ ) {
insertNode(&root,dataset[i]);
}
}
//插入新节点//注意因为要修改root根指针的值,所以需要传入二级指针bool BSearchTree:: insertNode(Node_t **root, int value) {
//初始化将插入的新节点
Node_t *new_node = new Node_t;
if ( new_node == NULL ) {
return false;
}
new_node->data = value;
new_node->leftchild = new_node->rightchild = new_node->parent = NULL;
//空树时,直接让根指针指向新节点
if( (*root) == NULL ) {
*root = new_node;
return true;
}
//插入到当前结点(*root)的左孩子
if ((*root)->leftchild == NULL && (*root)->data > value ) {
new_node->parent = (*root);
(*root)->leftchild = new_node;
return true;
}
//插入到当前结点(*root)的右孩子
if((*root)->rightchild == NULL && (*root)->data < value){
new_node->parent = (*root);
(*root)->rightchild = new_node;
return true;
}
//递归法插入新节点
if ( (*root)->data > value ) { //新节点的值小于根节点,递归寻找左边空位
insertNode( &(*root)->leftchild,value); //关键点
}
else if ( (*root)->data < value ) { //新节点的值大于根节点,递归寻找右边空位
insertNode( &(*root)->rightchild,value);
} else {
return true;
}
}
//中序遍历void BSearchTree:: inorderTraverse(Node_t *root) const {
//递归出口
if ( root == NULL ) {
return;
}
inorderTraverse( root->leftchild );
cout<< root->data <<" ";
inorderTraverse( root->rightchild );
}void BSearchTree::visitMiddleOrder() const {
inorderTraverse(this->root);
}
//按值查找,返回节点的地址
Node_t* BSearchTree:: searchNode(Node_t *root,int value) const {
if ( root == NULL ) {
return NULL;
}
if ( root->data > value ) {
searchNode( root->leftchild,value);
}
else if ( root->data < value ) {
searchNode( root->rightchild,value);
} else {
return root;
}
}void BSearchTree:: searchByValue(int value) const{
Node_t *p_findnode = this->searchNode(root,value);
if ( p_findnode == NULL ) {
cout<<"没有找到该节点"<<endl;
} else {
cout<< "该节点存在" <<endl;
}
}
//获取最大值void BSearchTree:: getMax(Node_t *root) const {
while( root->rightchild ) {
root = root->rightchild;
}
cout<<root->data<<endl;
}
//获取最小值void BSearchTree:: getMin(Node_t *root) const {
while( root->leftchild ) {
root = root->leftchild;
}
cout<<root->data<<endl;
}
//获取节点前驱void BSearchTree:: getPredecessor(Node_t *node) {
//节点如果有左子树,则其前驱节点是左子树的最大值
if ( node->leftchild != NULL ) {
return getMax( node->leftchild );
} else {
cout<<"(该点无左子树,开始回溯祖先...)"<<endl;
}
//如果没有右子树,则向上回溯,最顶层的祖先节点则是后继
Node_t *y = node->parent; //y首先指向该节点的父节点
while( y != NULL && node == y->leftchild ) {
node = y;
y = y->parent;
}
cout<<y->data;
}
//获取节点后继void BSearchTree:: getSuccessor(Node_t *node) {
//节点如果有右子树,则其后继节点是右子树的最小值
if ( node->rightchild != NULL ) {
return getMin( node->rightchild );
} else {
cout<<"(该点无右子树,开始回溯祖先...)"<<endl;
}
//如果没有右子树,则向上回溯,最顶层的祖先节点则是后继
Node_t *y = node->parent;
while( y != NULL && node == y->rightchild ) { //遇到第一个“拐角”回溯结束
node = y; //节点向上爬一层
y = y->parent; //y也向上逐层回溯祖先
}
cout<<y->data;
}
//返回树高,树通用写法//ps:算法导论认为只有一个根节点时树高为0,我们常认为1int BSearchTree::getHeight(Node_t *root) const {
return root ? max(getHeight(root->leftchild),getHeight(root->rightchild))+1 : -1;
}
【图书馆】
【选择】
void SelectSort(int *a, int len)
{
for (int i=0; i<len-1; i++)
{
int k = i;
int key = a[i];
for (int j=i+1; j<len; j++)
{
if (a[j]<key)
{
k = j;
key = a[j];
}
}
if (k!=i)
swap(a[i], a[k]);
}
}
【希尔】
【堆】
// 最大堆调整
void MaxHeapify(int *a, int i, int heapSize)
{
int l = (i+1)*2-1;
int r = (i+1)*2;
int largest;
if (l<=heapSize && a[l]>a[i])
largest = l;
else
largest = i;
if (r<=heapSize && a[r]>a[largest])
largest = r;
if (largest!=i)
{
swap(a[i], a[largest]);
MaxHeapify(a, largest, heapSize);
}
}
// 创建最大堆
void BuildMaxHeap(int *a, int len)
{
for (int i=len/2-1; i>=0; i--)
{
MaxHeapify(a, i, len-1);
}
}
// 堆排序
void HeapSort(int *a, int len)
{
BuildMaxHeap(a, len);
for (int i=len-1; i>0; i--)
{
swap(a[0], a[i]);
MaxHeapify(a, 0, i-1);
}
}
【快速】
(http://blog.csdn.net/acm_1361677193/article/details/48206603)
http://blog.sina.com.cn/s/blog_5c5bc9070100y4zv.html
void SelectSort(int *a, int len)
{
for (int i=0; i<len-1; i++)
{
int k = i;
int key = a[i];
for (int j=i+1; j<len; j++)
{
if (a[j]<key)
{
k = j;
key = a[j];
}
}
if (k!=i)
swap(a[i], a[k]);
}
}
gpu排序
【CUDA sample】
快排 quickSort: Stream 递归深度
双调排序 bitcoinSort
归并排序mergeSort【CUDA libarary thrust】http://bbs.csdn.net/topics/390810280
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/generate.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
#include <cstdlib>
#define NUM_ELEM (1024 * 1024)
int main(void)
{
thrust::host_vector<int> host_array(NUM_ELEM);
thrust::generate(host_array.begin(), host_array.end(), rand);
thrust::device_vector<int> device_array = host_array;
thrust::sort(device_array.begin(), device_array.end());
thrust::sort(host_array.begin(), host_array.end());
thrust::host_vector<int> host_array_sorted = device_array;
return 0;
}