Sort of principle

a

table of Contents

  1. Bubble Sort
  2. Direct insertion sort
  3. Simple selection sort
  4. Shell sort
  5. Merge sort
  6. Heapsort
  7. Quick Sort
  8. Counting Sort
  9. Bucket sort
  10. Radix Sort

A bubble sort

The basic idea is: the keyword comparison twenty-two adjacent recording, if the exchange reverse order

The best case time complexity of bubble sort \ (O (n-) \) , the worst case \ (O (n ^ 2) \)

Improvement of the 1: Flag is set, if there is obviously no trip occurs exchange \ ((= In Flag to false) \) , described sorting has been completed

Improvement of the 2: record the last position of a marker down, the next traverse from head to this location on Ok

Second, direct insertion sort

You will have a record into the sorted order of the table, thereby obtaining a new record ordered by number in Table 1

The time complexity is also \ (O (^ n-2) \) , and selective than the bubble sort performance is better

Third, the simple selection sort

By \ (Ni \) comparison between Keywords, from (ni + 1 \) \ recording select the smallest key record, and the first and \ (i (1 \ leq i \ leq n) \ ) records the exchange of

Although the same bubble sort \ (O (^ n-2) \) , but simply sorting performance slightly better than the bubble sort

Fourth, Hill sorting

The entire first row of elements of the sequence to be divided into sub-sequences (separated by the element a "delta" composition) were direct insertion sort, followed by further reducing the discharge increments

Timing to be the basic element in the sequence of the entire order (incremental sufficiently small), then all elements of a direct insertion sort (in increments of 1). Its time complexity is \ (O (\ {n-FRAC. 3} ^ {2}) \) , better than direct insertion sort of \ (O (n ^ 2) \)

Fifth, merge sort

It assumed that the initial sequence contains \ (n-\) records, may be viewed as \ (n-\) ordered subsequence, each subsequence of length \ (1 \) , then merge twenty-two give \ (\ lceil \ FRAC {n-2}} {\ rceil \) (not less than \ (\ frac {n} { 2} \) is the smallest integer) of length \ (2 \) or \ (1 \) ordered sequence then twenty-two merge, ...

Repeat, until a length of a \ (n-\) until the ordered sequence, this ordering method is called \ (2 \) path merge sort.

Time complexity is \ (O (nlogn) \) , the spatial complexity degree \ (O (n-+ logN) \) , if the non-recursive merge, is avoided when the recursion depth \ (logN \) stack space

Spatial complexity is \ (O (n) \)

Sixth, heap sort

Heap is a complete binary tree with the following properties: the value of each node is equal to or greater than the value of the left and right child nodes, referred to as large a top stack; each node or a value less than or equal to the value of its left child node, called top small heap.

The method is the use of heap sort heap sort of basic idea is:

Ordered sequence to be configured into a large pile top. At this time, the maximum value of the root node is the top of the stack of the entire sequence. It to be removed (which is actually the last element of the stack array exchange element is the end of this time Max), then the remaining \ (n-1 \) sequence reconfigured to a stack, this will give \ (n-) \ secondary value elements.

So again executed, it will be able to get an ordered sequence of.

Time complexity is \ (O (nlogn) \) , better than the bubble, simply, directly into the \ (O (n ^ 2) \)

Seven, quick sort

By ordering the trip data to be sorted into two separate portions, wherein a portion of all of the data than the other portion of all the data to be small, then this method to quickly sort the data two portions respectively, the entire sorting process can be recursively, in order to achieve the entire data becomes an ordered sequence. Time complexity is \ (O (nlogn) \)

Note: The above \ (7 \) species are relatively ordered, the following \ (3 \) species are non-sorted comparison, can theoretically reach \ (O (n-) \) , faster than comparative sort, but this \ (3 \) species all have their applications in order to play a role in the background, or just the opposite.

Eight, counting sort

Counting sequencing is a stable sorting algorithm. Counting sequencing using an additional array \ (C \) , where the first \ (I \) element is to be sorted array \ (A \) value is equal to \ (I \) number of elements. The array is then \ (C \) to the \ (A \) in an element first into the correct position.

Steps of the algorithm are as follows:

The array to be sorted to find the largest and smallest element

Statistics for each value in the array \ (i \) number of elements appear, into an array \ (C \) of the \ (i \) key

All accumulated counts (from (C \) \ in position \ (1 \) beginning with the elements, and each of the preceding addition)

Reverse fill the target array: each element \ (I \) first in the new array \ (C (i) \) items, each element will put a \ (C (i) \) subtracting \ (1 \)

Since the array for counting \ (C \) the length of the data in the array to be sorted depending on the range (difference between the maximum and the minimum value is equal to the array to be sorted plus \ (1 \) ), which makes the data counting sequencing range very large array, requires a lot of time and memory.

Nine, bucket sort

Or so-called bucket sort sorting boxes, it is a sorting algorithm, the principle is to be assigned to an array of a limited number of a bucket. Each individual bucket and then sorted (it is possible to re-use or other sorting algorithm recursively continue using bucket sort sorting)

Bucket sort performed in the following procedure:

Set a quantitative array as an empty bucket.
Serial search, and place the items one by one to a corresponding bucket. (Hash)
for each bucket is not empty sort.
From the house is not empty bucket and then back into the project in the original serial.

Ten, radix sort

Radix sort comparison type is a non-integer sorting algorithm, the principle is the integer number of bits is cut by different numbers, then the number of bits for each were compared. Since the integer can be expressed floating-point strings (such as name or date) and a specific format, the radix sort is not only used for integer.

It is implemented: all the values ​​to be compared (a positive integer) for the same number of uniform bit length, the shorter number of digits with leading zeros. Then, from the lowest Start, once sorted. This has been sorted from the lowest to the highest order of the bits is completed, the series becomes an ordered sequence.

Radix sort methods can be used LSD (Least significant digital) or MSD (Most significant digital), LSD are sorted starting from the rightmost key, and MSD on the contrary, starting from the leftmost keys.

#include<iostream>
using namespace std;

void swap1(int *left, int *right)
{
    int temp = *left;
    *left = *right;
    *right = temp;
}

void swap2(int &left, int &right)
{
    int temp = left;
    left = right;
    right = left;
}

void swap3(int &left, int &right)
{
    if (&left != &right) 
    {
        left ^= right;
        right ^= left;
        left ^= right;
    }
}

/*****************************************************************/
/* 冒泡排序时间复杂度最好的情况为O(n),最坏的情况是O(n^2)
* 基本思想是:两两比较相邻记录的关键字,如果反序则交换 */

void BubbleSort1(int arr[], int num)
{
    int i, j;
    for (i = 0; i < num; i++)
    {
        for (j = 1; j < num - i; j++)
        {
            if (arr[j - 1] > arr[j])
                swap1(&arr[j - 1], &arr[j]);
        }
    }
}

// 改进思路:设置标志位,明显如果有一趟没有发生交换(flag = flase),说明排序已经完成.
void BubbleSort2(int arr[], int num)
{
    int k = num;
    int j;
    bool flag = true;
    while (flag)
    {
        flag = false;
        for (j = 1; j < k; j++)
        {
            if (arr[j - 1] > arr[j])
            {
                swap1(&arr[j - 1], &arr[j]);
                flag = true;
            }
        }
        k--;
    }
}
//改进思路:记录一轮下来标记的最后位置,下次从头部遍历到这个位置就Ok
void BubbleSort3(int arr[], int num)
{
    int k, j;
    int flag = num;
    while (flag > 0)
    {
        k = flag;
        flag = 0;
        for (j = 1; j < k; j++)
        {
            if (arr[j - 1] > arr[j])
            {
                swap1(&arr[j - 1], &arr[j]);
                flag = j;
            }
        }
    }
}
/*************************************************************************/

/**************************************************************************/
/*插入排序: 将一个记录插入到已经排好序的有序表中, 从而得到一个新的,记录数增1的有序表
* 时间复杂度也为O(n^2), 比冒泡法和选择排序的性能要更好一些 */

void InsertionSort(int arr[], int num)
{
    int temp;
    int i, j;
    for (i = 1; i < num; i++)
    {
        temp = arr[i];
        for (j = i; j > 0 && arr[j - 1] > temp; j--)
            arr[j] = arr[j - 1];
        arr[j] = temp;
    }
}

/****************************************************************************/

/*希尔排序:先将整个待排元素序列分割成若干子序列(由相隔某个“增量”的元素组成的)分别进行
直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,
再对全体元素进行一次直接插入排序(增量为1)。其时间复杂度为O(n^3/2),要好于直接插入排序的O(n^2) */
void ShellSort(int *arr, int N)
{
    int i, j, increment;
    int tmp;
    for (increment = N / 2; increment > 0; increment /= 2)
    {
        for (i = increment; i < N; i++)
        {
            tmp = arr[i];
            for (j = i; j >= increment; j -= increment)
            {
                if (arr[j - increment] > tmp)
                    arr[j] = arr[j - increment];
                else
                    break;
            }
            arr[j] = tmp;
        }

    }
}

/**************************************************************************/

/* 简单选择排序(simple selection sort) 就是通过n-i次关键字之间的比较,从n-i+1
* 个记录中选择关键字最小的记录,并和第i(1<=i<=n)个记录交换之
* 尽管与冒泡排序同为O(n^2),但简单选择排序的性能要略优于冒泡排序 */

void SelectSort(int arr[], int num)
{
    int i, j, Mindex;
    for (i = 0; i < num; i++)
    {
        Mindex = i;
        for (j = i + 1; j < num; j++)
        {
            if (arr[j] < arr[Mindex])
                Mindex = j;
        }

        swap1(&arr[i], &arr[Mindex]);
    }
}

/********************************************************************************/
/*假设初始序列含有n个记录,则可以看成n个有序的子序列,每个子序列的长度为1,然后
* 两两归并,得到(不小于n/2的最小整数)个长度为2或1的有序子序列,再两两归并,...
* 如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序
* 时间复杂度为O(nlogn),空间复杂度为O(n+logn),如果非递归实现归并,则避免了递归时深度为logn的栈空间
* 空间复杂度为O(n) */


/*lpos is the start of left half, rpos is the start of right half*/
void merge(int a[], int tmp_array[], int lpos, int rpos, int rightn)
{
    int i, leftn, num_elements, tmpos;

    leftn = rpos - 1;
    tmpos = lpos;
    num_elements = rightn - lpos + 1;

    /*main loop*/
    while (lpos <= leftn && rpos <= rightn)
        if (a[lpos] <= a[rpos])
            tmp_array[tmpos++] = a[lpos++];
        else
            tmp_array[tmpos++] = a[rpos++];

    while (lpos <= leftn) /*copy rest of the first part*/
        tmp_array[tmpos++] = a[lpos++];
    while (rpos <= rightn) /*copy rest of the second part*/
        tmp_array[tmpos++] = a[rpos++];

    /*copy array back*/
    for (i = 0; i < num_elements; i++, rightn--)
        a[rightn] = tmp_array[rightn];
}


void msort(int a[], int tmp_array[], int left, int right)
{
    int center;

    if (left < right)
    {
        center = (right + left) / 2;
        msort(a, tmp_array, left, center);
        msort(a, tmp_array, center + 1, right);
        merge(a, tmp_array, left, center + 1, right);
    }
}



void merge_sort(int a[], int n)
{
    int *tmp_array;
    tmp_array = (int *)malloc(n * sizeof(int));

    if (tmp_array != NULL)
    {
        msort(a, tmp_array, 0, n - 1);
        free(tmp_array);
    }

    else
        printf("No space for tmp array!\n");
}

/************************************************************************************/
/* 堆是具有下列性质的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆;
* 或者每个节点的值都小于或等于其左右孩子节点的值,称为小顶堆*/

/*堆排序就是利用堆进行排序的方法.基本思想是:将待排序的序列构造成一个大顶堆.此时,整个序列的最大值就是堆顶
* 的根结点.将它移走(其实就是将其与堆数组的末尾元素交换, 此时末尾元素就是最大值),然后将剩余的n-1个序列重新
* 构造成一个堆,这样就会得到n个元素的次大值.如此反复执行,便能得到一个有序序列了
*/
/* 时间复杂度为 O(nlogn),好于冒泡,简单选择,直接插入的O(n^2) */

// 构造大顶堆
#define leftChild(i) (2*(i) + 1)

void percDown(int *arr, int i, int N)
{
    int tmp, child;
    for (tmp = arr[i]; leftChild(i) < N; i = child)
    {
        child = leftChild(i);
        if (child != N - 1 && arr[child + 1] > arr[child])
            child++;
        if (arr[child] > tmp)
            arr[i] = arr[child];
        else
            break;
    }
    arr[i] = tmp;
}

void HeapSort(int *arr, int N)
{
    int i;
    for (i = N / 2; i >= 0; i--)
        percDown(arr, i, N);
    for (i = N - 1; i > 0; i--)
    {
        swap1(&arr[0], &arr[i]);
        percDown(arr, 0, i);
    }
}



    
    #include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

/*****************计数排序*******************************/
void  CountSort(int *arr, int num)
{
    int mindata = arr[0];
    int maxdata = arr[0];
    for (int i = 1; i < num; i++)
    {
        if (arr[i] > maxdata)
            maxdata = arr[i];
        if (arr[i] < mindata)
            mindata = arr[i];
    }
    
    int size = maxdata - mindata + 1;
    //申请空间并初始化为0
    int *pCount = (int *)malloc(sizeof(int) * size);
    memset(pCount, 0, sizeof(int)*size);

    //记录排序计数,每出现一次在对应位置加1
    for (int i = 0; i < num; i++)
        ++pCount[arr[i]-mindata];

    //确定不比该位置大的数据个数
    for (int i = 1; i < size; i++)
        pCount[i] += pCount[i - 1]; //加上前一个的计数

    int *pSort = (int *)malloc(sizeof(int) * num);
    memset((char*)pSort, 0, sizeof(int) * num);

    //从末尾开始拷贝是为了重复数据首先出现的排在前面,即稳定排序
    for (int i = num - 1; i >= 0; i--)
    {
        //包含自己需要减1,重复数据循环回来也需要减1
        --pCount[arr[i]-mindata];
        pSort[pCount[arr[i]-mindata]] = arr[i];
    }
    //拷贝到原数组
    for (int i = 0; i < num; i++)
        arr[i] = pSort[i];

    free(pCount);
    free(pSort);

}

/*****************桶排序*****************************/
struct Node
{
    int key_;
    struct Node *next_;
    Node(int key)
    {
        key_ = key;
        next_ = NULL;
    }
};

#define bucket_size 10 //与数组元素个数相等

void buck_sort(int arr[], int num)
{
    Node *bucket_table[bucket_size];
    memset(bucket_table, 0, sizeof(bucket_table));

    //建立每一个头节点,头节点的key保存当前桶的数据量
    for (int i = 0; i < bucket_size; i++)
        bucket_table[i] = new Node(0);
    
    int maxValue = arr[0];
    for (int i = 1; i < num; i++)
    {
        if (arr[i] > maxValue)
            maxValue = arr[i];
    }

    for (int j = 0; j < num; j++)
    {
        Node *ptr = new Node(arr[j]);//其余节点的key保存数据

        //映射函数计算桶号
        // index = (value * number_of_elements) / (maxvalue + 1)
        int index = (arr[j] * bucket_size) / (maxValue + 1);
        Node *head = bucket_table[index];
        //该桶还没有数据
        if (head->key_ == 0)
        {
            bucket_table[index]->next_ = ptr;
            (bucket_table[index]->key_)++;

        }
        else
        {
            //找到合适的位置插入
            while (head->next_ != NULL && head->next_->key_ <= ptr->key_)
                head = head->next_;
            ptr->next_ = head->next_;
            head->next_ = ptr;
            (bucket_table[index]->key_)++;
        }

    }

    //将桶中的数据拷贝回原数组
    int m, n;
    for (m = 0, n = 0;  n < num && m < bucket_size; m++, n++)
    {
        Node *ptr = bucket_table[m]->next_;
        while (ptr != NULL)
        {
            arr[n] = ptr->key_;
            ptr = ptr->next_;
            n++;
        }
        n--;
    }

    //释放分配的动态空间
    for (m = 0; m < bucket_size; m++)
    {
        Node *ptr = bucket_table[m];
        Node *tmp = NULL;
        while (ptr != NULL)
        {
            tmp = ptr->next_;
            delete ptr;
            ptr = tmp;
        }

    }

}


/****************************************************/



/******************** 基数排序LSD*********************/

void base_sort_ISD(int *arr, int num)
{
    Node *buck[10]; // 创建一个链表数组
    Node *tail[10]; //保存每条链表尾节点指针集合,
    //这样插入buck数组时就不用每次遍历到末尾
    int  i, MaxValue, kth, high, low;
    Node *ptr;
    for(MaxValue = arr[0], i = 1; i < num; i++)
        MaxValue = max(MaxValue, arr[i]);

    memset(buck, 0, sizeof(buck));
    memset(tail, 0, sizeof(buck));

    for(low = 1; high = low * 10, low < MaxValue; low *= 10)
    {
        //只要没排好序就一直排序
        for(i = 0; i < num; i++)
        {
            //往桶里放
            kth = (arr[i] % high) / low;//取出数据的某一位,作为桶的索引
            ptr = new Node(arr[i]); //创建新节点

            //接到末尾
            if (buck[kth] != NULL)
            {
                tail[kth]->next_ = ptr;
                tail[kth] = ptr;
            }
            else
            {
                buck[kth] = ptr;
                tail[kth] = ptr;
            }

        }
        //把桶中的数据放回数组中(同条链表是从头到尾)
        for (kth = 0, i = 0; kth < num; i++)
        {
            while (buck[i] != NULL)
            {
                arr[kth++] = buck[i]->key_;
                ptr = buck[i];
                buck[i] = buck[i]->next_;
                delete ptr;
            }
        }

        memset(tail, 0, sizeof(buck));

    }

}
/**************************************************************/

int main(void)
{

    int arr1[] = {10, 15, 11, 20, 15, 18, 19, 12, 14, 17};
    int size1 = sizeof(arr1) / sizeof(arr1[0]);
    CountSort(arr1, size1);
    for (int i = 0; i < size1; i++)
        printf("%d ", arr1[i]);
    printf("\n");

    int arr2[] = {54, 8, 216, 512, 27, 729, 0, 1, 343, 125};
    int size2 = sizeof(arr2) / sizeof(arr2[0]);     
  base_sort_ISD(arr2, size2);     

  for (int i = 0; i < size2; i++)         
    printf("%d ", arr2[i]);     
  printf("\n");     

  int arr3[] = {49, 38, 65, 97, 76, 13, 27, 49, 132, 134};     

  int size3 = sizeof(arr3) / sizeof(arr3[0]);     
  buck_sort(arr3, size3);     

  for (int i = 0; i < size3; i++)        
    printf("%d ", arr3[i]);     
  printf("\n");     

  return 0; 
}
/*
int main(void)
{
    int arr[] = { 9, 2, 5, 8, 3, 4, 7, 1, 6, 10};
    HeapSort(arr, 10);
    for (int i = 0; i < 10; i++)         cout << arr[i] << ' ';     cout << endl;     return 0; }
    */

Guess you like

Origin www.cnblogs.com/liuziwen0224/p/11991505.html
Recommended