排序问题

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[]为临时数组,leftright分别是数组两端*/
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[]为临时数组,leftright分别是数组两端*/
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]);
    }
}
#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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值