《算法导论》 读书笔记 (二)

第二部分 排序

堆排序

堆(二叉堆):

二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最大堆和最小堆。最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

思想:
1.从原始序列构建最大堆
2.将堆顶元素与堆的最后一个元素互换,删除最后一个元素,并调整当前堆为最大堆
3.循环执行(2)直到堆中只有一个元素

实现:

#include<iostream>
#include<vector>

using namespace std;

vector<int> build_maxheap(vector<int> heap, int size);

vector<int> max_heapify(vector<int> heap, int p, int heap_size);

int n;
int main()
{
    vector<int> arr;
    int temp = 1;
    for (int i=10; i>0; i--)
    arr.push_back(i);
    for (int k=1; k<10; k++)
        {
         temp = temp * 2;
         if (temp >= arr.size() )
         {
           n = temp - 1;
          break;
         }
        }
    vector<int> heap;
    for (int i=0; i< n; i++)
        heap.push_back(0);
    for (int i=0; i< n; i++)
        heap[i] = arr[i];

    heap = build_maxheap(heap, arr.size());
    int heap_size = arr.size();
    for (int i=heap_size-1; i>0; i--)
       {
        int tempvalue = heap[i];
        heap[i] = heap[0];
        heap[0] = tempvalue;
        heap_size = heap_size - 1;
        heap = max_heapify(heap , 0, heap_size);
       }
    for (int i=0; i<arr.size(); i++)
       {
        cout << heap[i] <<" ";
       }
    cout <<endl;
    return 0;
}

vector<int> build_maxheap(vector<int> heap, int size)
{
    for (int i= (heap.size()+1)/2 -2; i>=0; i--)
        heap = max_heapify( heap , i,  size);
    return heap;
}

vector<int> max_heapify(vector<int> heap, int p, int heap_size)
{   
    int largest;
    int tempV;
    int l = 2 * p + 1;
    int r = 2 * p + 2;
    if((l < heap_size) && (heap[l] > heap[p]))
        largest = l;
    else
        largest = p;    
    if((r < heap_size) && (heap[r] > heap[largest]))
        largest = r;
    if (largest != p)
        {
        tempV = heap[p];
        heap[p] = heap[largest];
        heap[largest] = tempV;
        heap = max_heapify(heap, largest, heap_size);
        }
    return heap;
}

优先级队列:
优先级队列可以用最大堆来实现

快速排序

思想:
在未排序序列中,重新安排次序,使得找到一个元素下标,使其前面的元素小于等于它,后面的元素大于等于它,然后再在前后两个子序列中递归调用此方法。

实现:

include<iostream>
#include<vector>

using namespace std;

vector<int> quick_sort(vector<int> arr, int start, int end);
int partition_q(vector<int> arr, int start, int end);
vector<int> partition_arr(vector<int> arr, int start, int end);
int q;

int main()
{
    vector<int> arr;
    for (int i=10; i>0; i--)
    arr.push_back(i);
    int start = 0;
    int end = arr.size() - 1;
    arr = quick_sort(arr, start, end);
    for (int i=0; i<arr.size(); i++)
       {
        cout << arr[i] <<" ";
       }
    cout <<endl;
    return 0;
}

vector<int> quick_sort(vector<int> arr, int start, int end)
{
    if (start < end )
        {
         q = partition_q(arr,start,end);
         arr = partition_arr(arr,start,end);
         arr = quick_sort(arr, start, q-1);
         arr = quick_sort(arr, q+1, end);
        }
    return arr;
}

int partition_q(vector<int> arr, int start, int end)
{   
    int x = arr[end];
    int i = start - 1;
    int temp;
    int tempv;
    for( int j = start; j<end; j++ )
    {
      if (arr[j] <= x)
         {
          i = i + 1;
          temp = arr[i];
          arr[i] = arr[j];
          arr[j] = temp;
         }
    }
    tempv = arr[i+1];
    arr[i+1] = arr[end];
    arr[end] = tempv;
    int q = i + 1; 
    return q;
}

vector<int> partition_arr(vector<int> arr, int start, int end)
{   
    int x = arr[end];
    int i = start - 1;
    int temp;
    int tempv;
    for( int j = start; j<end; j++ )
    {
      if (arr[j] <= x)
         {
          i = i + 1;
          temp = arr[i];
          arr[i] = arr[j];
          arr[j] = temp;
         }
    }
    tempv = arr[i+1];
    arr[i+1] = arr[end];
    arr[end] = tempv;
    int q = i + 1; 
    return arr;
}

线性时间排序

1.计数排序

应用范围: 整数

思想:
假设输入的线性表L的长度为n,L=L1,L2,..,Ln;线性表的元素属于有限偏序集S,|S|=k且k=O(n),S={S1,S2,..Sk};则计数排序可以描述如下:
1、扫描整个集合S,对每一个Si∈S,找到在线性表L中小于等于Si的元素的个数T(Si);
2、扫描整个线性表L,对L中的每一个元素Li,将Li放在输出线性表的第T(Li)个位置上,并将T(Li)减1。

2.基数排序(桶排序)

应用范围:整数,所有数位数相同

思想:

假设原来有一串数值如下所示:
73, 22, 93, 43, 55, 14, 28, 65, 39, 81
首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:
0
1 81
2 22
3 73 93 43
4 14
5 55 65
6
7
8 28
9 39

接下来将这些桶子中的数值重新串接起来,成为以下的数列:
81, 22, 73, 93, 43, 14, 55, 65, 28, 39

接着再进行一次分配,这次是根据十位数来分配:
0
1 14
2 22 28
3 39
4 43
5 55
6 65
7 73
8 81
9 93

接下来将这些桶子中的数值重新串接起来,成为以下的数列:
14, 22, 28, 39, 43, 55, 65, 73, 81, 93
这时候整个数列已经排序完毕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值