插入排序:
默认升序,向已排序的数组中插入新的元素,要求插入后的数组仍然为升序。
方法:
按照从后往前的顺序将新元素与数组中的元素比较,直到找到第一个小于新元素的
元素,其所在的位置即为新元素的位置。
#include <iostream>
using std::cout;
using std::endl;
class insert
{
public:
insert(int *arr,const int size);
~insert();
void sort();
private:
int *vec;
int len;
};
insert::insert(int *arr, const int size)
{
if (size > 0)
{
vec = new int[size];
if (NULL != vec)
{
len = size;
for (int i = 0; i < size; ++i)
*(vec+i) = *(arr+i);
}
}
}
insert::~insert()
{
if (NULL != vec)
{
for (int i = 0; i < len; ++i)
cout << *(vec+i) << " ";
cout << endl;
delete []vec;
vec = NULL;
}
}
void insert::sort()
{
int key;
for (int i = 1; i < this->len; ++i)
{
int key = vec[i], j = i-1;
while (vec[j] > key && j >= 0)
{
vec[j+1] = vec[j];
--j;
}
vec[j+1] = key;
}
}
int main()
{
int arr[10] = {100, 70, -90, 0, 1, -500, 800, -1000, -22, 88};
int i = 0;
for (i = 0; i < 10; ++i)
cout << arr[i] << " ";
cout << endl;
insert ins(arr, 10);
ins.sort();
return 0;
}
-----------------------------------------------
二路归并排序
方法:将n个元素分成各含n/2个元素的子序列,用合并排序法对两个子序列递归地排序,
合并两个已排序的子序列以得到排序结果
#include <iostream>
using std::cout;
using std::endl;
void merge(int arr[], int bgn, int mid, int end)
{
int *left = new int[mid-bgn+1];
int *right = new int[end-mid];
if (NULL == left || NULL == right)
return;
int i, j, k;
for (i = bgn, k = 0; i <= mid; ++i)
*(left+k++) = *(arr+i);
for (i = mid+1, k = 0; i <= end; ++i)
*(right+k++) = *(arr+i);
i = 0, j = 0, k = bgn;
while (i <= (mid-bgn) && j <= (end-mid-1))
{
if (*(left+i) < *(right+j))
*(arr+k++) = *(left+i++);
else
*(arr+k++) = *(right+j++);
}
for (;i <= (mid-bgn); ++i)
*(arr+k++) = *(left+i);
for (;j <= (end-mid-1); ++j)
*(arr+k++) = *(right+j);
cout << "---------- bgn = " << bgn << " , end = " << end << endl;
for (int i = bgn; i <= end; ++i)
cout << arr[i] << " ";
cout << endl;
cout << "--------- end" << endl;
delete []left;
left = NULL;
delete []right;
right = NULL;
}
void mergesort(int arr[], int bgn, int end)
{
if (bgn < end)
{
int mid = (bgn+end)/2;
mergesort(arr, bgn, mid);
mergesort(arr, mid+1, end);
merge(arr, bgn, mid, end);
}
}
int main()
{
int i, arr[] = {5, 2, 4, 7, 1, 3, 2, 6, -9};
for (i = 0; i < 9; ++i)
cout << arr[i] << " ";
cout << endl;
mergesort(arr, 0, 8);
for (i = 0; i < 9; ++i)
cout << arr[i] << " ";
cout << endl;
return 0;
}
------------------------------------------------------
/*
堆:若将序列所存储的arr[1,n]看做是一棵完全二叉树的存储结构,
树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字
堆排序:
1.将要排序的数组创建为一个大根堆。大根堆的堆顶元素就是这个堆中最大的元素。
2.将大根堆的堆顶元素和无序区最后一个元素交换,并将无序区最后一个位置加入有序区,
然后将新的无序区调整为大根堆。重复操作,无序区在递减,有序区在递增。
*/
#include <iostream>
using std::cout;
using std::endl;
#define LEFT(i) ((i<<1)+1)
#define RIGHT(i) ((i<<1)+2)
// 为了始终保持大根堆的属性,对堆中的第i个元素进行调整
void max_heapify(int arr[], int i, int heapsize)
{
int l = LEFT(i);
int r = RIGHT(i);
// 找出i节点及其左右孩子的最大值的index
int largest = i;
if (l < heapsize)
{
if (arr[l] >= arr[i])
largest = l;
else
largest = i;
}
if (r < heapsize && arr[r] >= arr[largest])
largest = r;
// 如果i节点最大,则不需要调整,否则交换i节点与其左右孩子中的较大者,
// 在其较大孩子所对应的子树中继续对i节点进行调整,直到满足大根堆的属性
if (largest != i)
{
int tmp = arr[largest];
arr[largest] = arr[i];
arr[i] = tmp;
max_heapify(arr, largest, heapsize);
}
}
// 由于大根堆是完全二叉树,所以建堆时,只需要调整非叶子节点
void build_max_heap(int arr[], int len)
{
for (int i = (len-1)>>1; i >= 0; --i)
max_heapify(arr, i, len);
}
// 堆排序:首先建立大根堆,由于大根堆的最大节点总是为arr[0]
// 将arr[0]与当前大根堆最后节点交换,这样就可以获取当前堆的
// 最大节点,减去当前堆的最大节点,继续按照大根堆的属性调整
// 当前剩余的节点
void heapsort(int arr[], int len)
{
int tmp;
build_max_heap(arr, len);
for (int i = len-1; i > 0; --i)
{
--len;
tmp = arr[0];
arr[0] = arr[i];
arr[i] = tmp;
max_heapify(arr, 0, len);
}
}
int main()
{
int i, arr[10] = {4, 1, 3 ,2, 16, 9, 10, 14, 8, 7};
for (i = 0; i < 10; ++i)
cout << arr[i] << " ";
cout << endl;
heapsort(arr, 10);
for (i = 0; i < 10; ++i)
cout << arr[i] << " ";
cout << endl;
return 0;
}
----------------------------------------------
/*
堆:若将序列所存储的arr[1,n]看做是一棵完全二叉树的存储结构,
树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字
最大优先队列的一个应用是在一个分时计算机上进行作业调度
*/
#include <iostream>
using std::cout;
using std::endl;
#define LEFT(i) ((i<<1)+1)
#define RIGHT(i) ((i<<1)+2)
#define PARENT(i) ((i-1)>>1)
// 为了始终保持大根堆的属性,对堆中的第i个元素进行调整
void max_heapify(int arr[], int i, int heapsize)
{
int l = LEFT(i);
int r = RIGHT(i);
// 找出i节点及其左右孩子的最大值的index
int largest = i;
if (l < heapsize)
{
if (arr[l] >= arr[i])
largest = l;
else
largest = i;
}
if (r < heapsize && arr[r] >= arr[largest])
largest = r;
// 如果i节点最大,则不需要调整,否则交换i节点与其左右孩子中的较大者,
// 在其较大孩子所对应的子树中继续对i节点进行调整,直到满足大根堆的属性
if (largest != i)
{
int tmp = arr[largest];
arr[largest] = arr[i];
arr[i] = tmp;
max_heapify(arr, largest, heapsize);
}
}
// 由于大根堆是完全二叉树,所以建堆时,只需要调整非叶子节点
void build_max_heap(int arr[], int len)
{
for (int i = (len-1)>>1; i >= 0; --i)
max_heapify(arr, i, len);
}
// 返回大根堆中的最大节点
int heap_maximum(int arr[])
{
return arr[0];
}
// 去除并返回大根堆中的最大节点
int heap_extract_max(int arr[], int len)
{
if (len < 1)
return -1;
int tmp = arr[0];
arr[0] = arr[len-1];
--len;
max_heapify(arr, 0, len);
return tmp;
}
// 将节点x的值提升到key,在key>arr[x]的前提下
bool heap_increase_key(int arr[], int x, int key)
{
if (arr[x] > key)
return false;
arr[x] = key;
int tmp;
while (x > 0 && arr[PARENT(x)] < arr[x])
{
tmp = arr[PARENT(x)];
arr[PARENT(x)] = arr[x];
arr[x] = tmp;
x = PARENT(x);
}
return true;
}
// 插入元素key
void max_heap_insert(int arr[], int len, int key)
{
arr[len] = -1;
++len;
heap_increase_key(arr, len-1, key);
}
int main()
{
int i, arr[20] = {4, 1, 3 ,2, 16, 9, 10, 14, 8, 7};
for (i = 0; i < 10; ++i)
cout << arr[i] << " ";
cout << endl;
build_max_heap(arr, 10);
for (i = 0; i < 10; ++i)
cout << arr[i] << " ";
cout << endl;
/*
cout << "heap_extract_max " << heap_extract_max(arr, 10) << endl;
for (i = 0; i < 9; ++i)
cout << arr[i] << " ";
cout << endl;
*/
max_heap_insert(arr, 10, 20);
for (i = 0; i < 11; ++i)
cout << arr[i] << " ";
cout << endl;
return 0;
}
------------------------------------------------------------------------------
/*
快速排序:选择一个key,从左边查找第一个比key大的元素与此交换,
然后,从右边查找第一个比key小的元素与此交换,不断重复这个过程;
最终,使其左边的元素均小于key,其右边的元素均大于key
*/
#include <iostream>
using std::cout;
using std::endl;
int partition(int arr[], int p, int r)
{
int key = arr[r], i = p, j = r;
while (i < j)
{
while (i < j && arr[i] < key) //find the first element great than key from left
++i;
if (i < j) // found
arr[j--] = arr[i];
while (i < j && arr[j] > key) //find the first element which less than key from right
--j;
if (i < j) // found
arr[i++] = arr[j];
}
arr[i] = key;
return i;
}
void qsort(int arr[], int p, int r)
{
int tmp = 0;
if (p < r)
{
tmp = partition(arr, p, r);
qsort(arr, p, tmp-1);
qsort(arr, tmp+1, r);
}
}
int main()
{
int arr[8] = {2, 8, 7, 1, 3, 5, 6, 4};
qsort(arr, 0 , 7);
for (int i = 0; i < 8; ++i)
cout << arr[i] << " ";
cout << endl;
return 0;
}