转载请注明出处,如果有笔误请联系我 qq 409746848,后续还会基础出教程,您的关注是我最大的动力。
冒泡
void MaoPao(int * arr , int size)
{
if(!arr || size <= 0) return;
//冒泡算法核心,从头到尾进行排序,每轮找出最小的和第一个进行交换
//时间复杂度是O(N平方)
for(int i=0;i<size ; i++)
{
//第二轮从第二个开始
for(int j=i+1;j<size;j++)
{
if(arr[i] > arr [j])
{
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
}
}
快排
void qsort(int * arr , int l , int h)
{
//如果低位>=高位表示结束
if(l>=h) return;
int i = l,j=h;
int key = arr[i];//关键位置用的是i就要先将i的值填充
while(i<j)
{
//右边找比key小的放左边
while(i<j && arr[j]>=key)
{
j--;
}
arr[i] = arr[j];
//左边找比key大的放右边
while(i<j && arr[i]<=key){
i++;
}
arr[j] = arr[i];
}
//关键值放入中间位置
arr[i] = key;
qsort(arr , l , i - 1);
qsort(arr, i +1 , h);
}
//-------------------------------------------------------------------------------
//选择排序
//-------------------------------------------------------------------------------
//选择排序
void selectSort(int* arr , int size)
{
//每一次都找出剩下队列中最小的并放置在当前的位置
for (int i=0;i<size;i++)
{
int minpos = i;
for (int j=i+1;j<size;j++)
{
if (arr[j] < arr[minpos])
{
minpos = j;
}
}
int tem = arr[i];
arr[i] = arr[minpos];
arr[minpos] = tem;
}
}
//堆排序
void adjustMaxHeap(int a[], int len, int parentNodeIndex) {
// 若只有一个元素,那么只能是堆顶元素,也没有必要再排序了
if (len <= 1) {
return;
}
// 记录比父节点大的左孩子或者右孩子的索引
int targetIndex = -1;
// 获取左、右孩子的索引
int leftChildIndex = 2 * parentNodeIndex + 1;
int rightChildIndex = 2 * parentNodeIndex + 2;
// 没有左孩子
if (leftChildIndex >= len) {
return;
}
// 有左孩子,但是没有右孩子
if (rightChildIndex >= len) {
targetIndex = leftChildIndex;
}
// 有左孩子和右孩子
else {
// 取左、右孩子两者中最大的一个
targetIndex = a[leftChildIndex] > a[rightChildIndex] ? leftChildIndex : rightChildIndex;
}
// 只有孩子比父节点的值还要大,才需要交换
if (a[targetIndex] > a[parentNodeIndex]) {
int temp = a[targetIndex];
a[targetIndex] = a[parentNodeIndex];
a[parentNodeIndex] = temp;
// 交换完成后,有可能会导致a[targetIndex]结点所形成的子树不满足堆的条件,
// 若不满足堆的条件,则调整之使之也成为堆
adjustMaxHeap(a, len, targetIndex);
}
}
void heapSort(int a[], int len) {
if (len <= 1) {
return;
}
// 初始堆成无序最大堆
// 从完全二叉树最后一个非子节点开始
// 在数组中第一个元素的索引是0
// 第n个元素的左孩子为2n+1,右孩子为2n+2,
// 最后一个非子节点位置在(n - 1) / 2
for (int i = (len - 1) / 2; i >= 0; --i) {
adjustMaxHeap(a, len, i);
}
for (int i = len - 1; i > 0; --i) {
// 将当前堆顶元素与最后一个元素交换,保证这一趟所查找到的堆顶元素与最后一个元素交换
// 注意:这里所说的最后不是a[len - 1],而是每一趟的范围中最后一个元素
// 为什么要加上>0判断?每次不是说堆顶一定是最大值吗?没错,每一趟调整后,堆顶是最大值的
// 但是,由于len的范围不断地缩小,导致某些特殊的序列出现异常
// 比如说,5, 3, 8, 6, 4序列,当调整i=1时,已经调整为3,4,5,6,8序列,已经有序了
// 但是导致了a[i]与a[0]交换,由于变成了4,3,5,6,8反而变成无序了!
if (a[0] > a[i]) {
int temp = a[0];
a[0] = a[i];
a[i] = temp;
}
// 范围变成为:
// 0...len-1
// 0...len-1-1
// 0...1 // 结束
// 其中,0是堆顶,每次都是找出在指定的范围内比堆顶还大的元素,然后与堆顶元素交换
adjustMaxHeap(a, i - 1, 0);
}
}
//-------------------------------------------------------------------------------
//插入排序
//-------------------------------------------------------------------------------
//普通插入排序
void InsertSort(int* arr , int size)
{
//从第一个元素开始,认为第一个元素是已经排序好的队列
//从后面元素中找到比前一个小的位置
//从这个位置向前遍历找到比这个位置小的位置插入,否则这个值就往后移动一个位置
for (int i = 1 ; i<size ; i++)
{
int prepos = i-1;
int curval = arr[i];
while(prepos >=0 && arr[prepos] > curval )
{
arr[prepos+1] = arr[prepos];
prepos-- ;
}
arr[prepos+1] = curval;
}
}
//折半插入排序(也叫希尔排序)
void HalfInsertSort(int* arr , int size)
{
//一半一半的执行插入排除
for (int i = size/2 ; i>0 ; i = i/2)
{
for (int j = i ; j<size ; j++)
{
int pos = j;
int curval = arr[j];
while(pos-i >= 0 && arr[pos-i] > curval)
{
//后移
arr[pos] = arr[pos-i];
pos = pos - i;
}
arr[pos] = curval;
}
}
}
//-------------------------------------------------------------------------------
//归并排序
//-------------------------------------------------------------------------------
//二路归并 和 多路归并
//对每一路进行归并排序
void MergeSort(int* arr , int* temp , int startindex,int endindex)
{
int mid = 0;
if (startindex < endindex)
{
mid = startindex+(endindex - startindex)/2;
MergeSort(arr,temp,startindex , mid);
MergeSort(arr,temp,mid+1 , endindex);
//合并两个数组
int i=startindex,k=startindex,j=mid+1;
//两部分对比,取更小的部分继续往后移动
while(i<mid+1 && j < endindex+1)
{
if (arr[i] > arr[j])
{
temp[k++] = arr[j++];
}
else
{
temp[k++] = arr[i++];
}
}
//复制左边剩下的
while(i < mid+1)
{
temp[k++] = arr[i++];
}
//复制右边剩下的
while(j<endindex+1)
{
temp[k++] = arr[j++];
}
//数组还原
for (i = startindex ; i<endindex+1 ; i++)
{
arr[i] = temp[i];
}
}
}
//-------------------------------------------------------------------------------
//非比较排序
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
//计数排序,比较的元素差值不要太大
//-------------------------------------------------------------------------------
void CountSort(int* arr , int size)
{
int max = arr[0],min = arr[0];
//找出最大和最小
for (int i=0;i<size;i++)
{
if (arr[i] > max) max = arr[i];
if (arr[i] < min) min = arr[i];
}
int newlen = max - min + 1;
int* newIntArr = new int[newlen];
memset(newIntArr , 0 , newlen*sizeof(int));
//开始计数
for (int i=0;i<size;i++)
{
newIntArr[ arr[i] - min ] += 1;
}
//开始取出有序填入原数组
for (int i=0,j=0;i<newlen ; i++)
{
while(newIntArr[i]--)
{
arr[j++] = i+min;
}
}
delete [] newIntArr;
}
//-------------------------------------------------------------------------------
//桶排序 是计数排序的升级版,需要知道:1.几个桶;2.每个桶有几个元素
//-------------------------------------------------------------------------------
typedef struct bucket{
int k;
bucket* next;
}bucket;
void bucketSort(int* arr , int size , int bucket_elm_size)
{
int min = arr[0] , max = arr[0];
for (int i=0;i<size;i++)
{
if(arr[i] > max) max = arr[i];
if(arr[i] < min) min = arr[i];
}
int bucket_count = (max - min) / bucket_elm_size + 1;
//初始化桶子
bucket* pbuckets = new bucket[bucket_count];
for(int i = 0 ;i<bucket_count ; i++)
{
pbuckets[i].k = 0;
pbuckets[i].next = 0;
}
//将数据入桶
for(int i = 0 ;i<size ; i++)
{
int index = (arr[i]-min)/bucket_elm_size;
bucket* pFindBucket = &pbuckets[index];
//使用插入排序
bucket* pNewBucket = new bucket;
pNewBucket->k = arr[i];
pNewBucket->next = NULL;
if (pFindBucket->k == 0)
{
pFindBucket->k += 1;
pFindBucket->next = pNewBucket;
}
else
{
while(pFindBucket->next != NULL && pFindBucket->next->k <= pNewBucket->k )
pFindBucket = pFindBucket->next;
pNewBucket->next = pFindBucket->next;
pFindBucket->next = pNewBucket;
pbuckets[index].k += 1;
}
}
//输出数据
for (int i=0,j=0;i<bucket_count;i++)
{
for(bucket* pBucket = pbuckets[i].next;pBucket!=NULL;)
{
bucket* tmp = pBucket;
arr[j++] = pBucket->k;
pBucket = pBucket->next;
delete tmp;
}
}
delete [] pbuckets;
}
//基数排序
//需要找到最大数,计算基数,然后存储基数
void RadixSort(int* arr , int size)
{
unsigned int max = 0;
for (int i=0;i<size;i++)
{
if (abs(arr[i]) > max)
{
max = abs(arr[i]);
}
}
int bucketCount = 10;
int radix = 1;//最大有多少个数量级
while(max / (int)pow((float)10,radix))
{
radix++;
}
bucket * pRadixArr = new bucket[10];
for (int i=0;i<bucketCount;i++)
{
pRadixArr[i].k = 0;
pRadixArr[i].next = NULL;
}
int mod = 10;//求余模数
int dev = 1;//除数
for (int i=0;i<radix;i++,dev *= 10 , mod *= 10)
{
for (int j = 0 ; j< size ; j++)
{
bucket* pNewBucket = new bucket;
pNewBucket->k = arr[j];
pNewBucket->next = NULL;
//求出个位或者10位对应的桶序号
int radixIndex = arr[j] % mod / dev;
bucket* pFind = &pRadixArr[radixIndex];
if (pFind->k == 0)
{
pFind->k += 1;
pFind->next = pNewBucket;
}
else
{
while(pFind->next != NULL && pFind->next->k <= pNewBucket->k) pFind = pFind->next;
pNewBucket->next = pFind->next;
pFind->next = pNewBucket;
pRadixArr[radixIndex].k += 1;
}
}
//从小到大取出桶的数据即可
int pos = 0;
for (int j = 0 ; j<bucketCount ; j++)
{
if (pRadixArr[j].k)
{
bucket* pNode = pRadixArr[j].next;
while(pNode)
{
bucket* pNodeDel = pNode;
arr[pos++] = pNode->k;
pNode = pNode->next;
delete pNodeDel;
}
pRadixArr[j].k = 0;
pRadixArr[j].next = NULL;
}
}
}
delete[] pRadixArr;
}
//十种排序算法
int _tmain(int argc, _TCHAR* argv[])
{
int aa[]={6,5,8,9,1,10,65,85,95,111,254,3,22,16,28};
int bb[ARRSIZE(aa)];
RadixSort(aa,ARRSIZE(aa));
bucketSort(aa,ARRSIZE(aa),5);
CountSort(aa , ARRSIZE(aa));
heapSort(aa , ARRSIZE(aa));
MergeSort(aa ,bb, 0,ARRSIZE(aa)-1);
HalfInsertSort(aa , ARRSIZE(aa));
InsertSort(aa,ARRSIZE(aa));
selectSort(aa,ARRSIZE(aa));
MaoPao(aa,ARRSIZE(aa));
qsort(aa,0,ARRSIZE(aa)-1);
return 0;
}