赞
踩
1.1思路:
直接插入排序是一种简单的插入排序法,其基本思想是: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
1.2步骤:
1.从第一个元素开始,该元素可以认为已经被排序
2.取下一个元素tem,从已排序的元素序列从后往前扫描
3.如果该元素大于tem,则将该元素移到下一位
4.重复步骤3,直到找到已排序元素中小于等于tem的元素
5.tem插入到该元素的后面,如果已排序所有元素都大于tem,则将tem插入到下标为0的位置
6.重复步骤2~5
1.3代码:
- void InsertSort(int* a, int n)//直接插入法,升序算法
- {
- for (int i = 1; i < n; i++)
- {
- int tmp = a[i];//tmp表示待插入的数据
- int end = i - 1;//end为tmp前一个数据
- while (end >= 0)//end往前移动,一一判断
- {
- if (tmp >=a[end])//如果tmp更大,直接跳出循环
- break;
- if (tmp < a[end])//如果tmp更小,则end再往前移
- {
- a[end + 1] = a[end];
- end--;
- }
- }
- a[end + 1] = tmp;
- //代码执行到此位置有两种情况:
- //1.待插入元素找到应插入位置(break跳出循环到此)
- //2.待插入元素比当前有序序列中的所有元素都小(while循环结束后到此)
- }
- }
插入排序:时间复杂度:o(n^2);空间复杂度:o (1);
2.1思路:
希尔排序,先将待排序列进行预排序,使待排序列接近有序,然后再对该序列进行一次插入排序,此时插入排序的时间复杂度为O(N)。(希尔排序本质上是对直接插入排序的升级,即先经过预排序,使数据接近与有序)
2.2步骤:
1.先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…
2.当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。
2.3代码:
- void ShellSort(int* a, int n)//希尔排序
- {
- int gap = n;
- while (gap > 1)
- {
- gap = gap / 3 + 1;//当gap等于1的时候实际上就是进行一遍快速排序
- //gap=gap/2;也可以
- for (int i = 0; i < n - gap; i++)
- {
- int tmp = a[i + gap];
- int end = i;
- while (end >= 0)
- {
- if (a[end] <= tmp)
- {
- break;
- }
- else
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- }
- a[end + gap] = tmp;
- }
- }
- }
希尔排序:时间复杂度:o(n^1.3);空间复杂度:o(1);
希尔排序的特性总结:
《数据结构-用面相对象方法与C++描述》--- 殷人昆 :
3.1思路:
每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完即可。
实际上,我们可以一趟选出两个值,一个最大值一个最小值,然后将其放在序列开头和末尾,这样可以使选择排序的效率快一倍。
3.2步骤:
3.3代码:
- void SelectSort(int* a, int left,int right)//选择排序,每次遍历同时选出最大值和最小值
- {
- int mini = left;
- int maxi = left;
- while (left < right)
- {
- for (int i = left; i <= right ; i++)
- {
- if (a[i] < a[mini])
- mini = i;
- if (a[i] > a[maxi])
- maxi = i;
- }
- Swap(&a[left], &a[mini]);//交换两个数的值
- if (left == maxi)//注意:但最左边元素是最大的元素时,此时交换right和maxi就会出错
- {
- maxi = mini;//让maxi重新指向最大的元素
- }
- Swap(&a[right], &a[maxi]);
- left++;
- right--;
- }
- }
选择排序:时间复杂度:o(n^2);空间复杂度:o(1);
4.1思路:
左边大于右边交换一趟排下来最大的在右边
4.2代码:
- void BubbleSort(int* a, int n)//冒泡排序
- {
- for (int i = 0; i < n; i++)
- {
- for (int j = 1; j < n - i; j++)
- {
- if (a[j] < a[j - 1])
- Swap(&a[j], &a[j - 1]);//交换两个数的值
- }
- }
- }
冒泡排序:时间复杂度:o(n^2);空间复杂度:o(1);
5.1思路:
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。堆排序需要建立在对堆数据结构十分了解的基础上。
由于篇幅原因这里直接呈现代码,如果读者对堆不太熟悉的,我推荐大家去看这篇博客:堆排序
5.2代码:
- void AdjustDown(int* a, int n, int parent)//向下调整算法
- {
- int child = parent * 2 + 1;
- while (child < n)
- {
- if (child+1<n&&a[child + 1] > a[child])
- child++;
- if (a[child] > a[parent])
- {
- Swap(&a[child], &a[parent]);
- parent = child;
- child = parent * 2 + 1;
- }
- else
- break;
- }
- }
- void HeapSort(int* a, int n)
- {
- for (int i = (n - 1 - 1) / 2; i >= 0; i--)//建堆
- AdjustDown(a, n, i);
- int end = n - 1;
- while (end >= 0)//排序
- {
- Swap(&a[0], &a[end]);
- AdjustDown(a, end, 0);
- end--;
- }
- }
堆排序:时间复杂度o(n*logn);空间复杂度o(1);
思路:
思路:
1、选出一个key,一般是最左边或是最右边的。
2、定义一个begin和一个end,begin从左向右走,end从右向左走。(需要注意的是:若选择最左边的数据作为key,则需要end先走;若选择最右边的数据作为key,则需要bengin先走)。
3、在走的过程中,若end遇到小于key的数,则停下,begin开始走,直到begin遇到一个大于key的数时,将begin和right的内容交换,end再次开始走,如此进行下去,直到begin和end最终相遇,此时将相遇点的内容与key交换即可。(选取最左边的值作为key)
4.此时key的左边都是小于key的数,key的右边都是大于key的数
5.将key的左序列和右序列再次进行这种单趟排序,如此反复操作下去,直到左右序列只有一个数据,或是左右序列不存在时,便停止操作,此时此部分已有序
代码:
- int PartSort1(int* a, int begin, int end)
- {
- int keyi = begin;
- int key = a[begin];
- while (begin < end)
- {
- while (begin < end && a[end] >= key)
- end--;
- while (begin < end && a[begin] <= key)
- begin++;
- Swap(&a[end], &a[begin]);
- }
- Swap(&a[end], &a[keyi]);
- return end;
- }
- void QuickSort(int* a, int begin, int end)
- {
- if (begin >= end)
- return;
- int keyi=PartSort1(a, begin, end);
- QuickSort(a, begin, keyi - 1);
- QuickSort(a, keyi + 1, end);
- }
思路:
挖坑法思路与hoare版本(左右指针法)思路类似
1.选出一个数据(一般是最左边或是最右边的)存放在key变量中,在该数据位置形成一个坑
2、还是定义一个L和一个R,L从左向右走,R从右向左走。(若在最左边挖坑,则需要R先走;若在最右边挖坑,则需要L先走)
代码:
- int PartSort2(int* a, int begin, int end)
- {
- int key= a[begin];
- int hole = begin;
- while (begin < end)
- {
- while (begin < end && a[end] >= key)
- end--;
- a[hole] = a[end];
- hole = end;
- while (begin < end && a[begin] <= key)
- begin++;
- a[hole] = a[begin];
- hole = begin;
- }
- a[hole] = key;
- }
- void QuickSort(int* a, int begin, int end)
- {
- if (begin >= end)
- return;
- int keyi=PartSort2(a, begin, end);
- QuickSort(a, begin, keyi - 1);
- QuickSort(a, keyi + 1, end);
- }
思路:
1、选出一个key,一般是最左边或是最右边的。
2、起始时,prev指针指向序列开头,cur指针指向prev+1。
3、若cur指向的内容小于key,则prev先向后移动一位,然后交换prev和cur指针指向的内容,然后cur指针++;若cur指向的内容大于key,则cur指针直接++。
如此进行下去,直到cur到达end位置,此时将key和++prev指针指向的内容交换即可。经过一次单趟排序,最终也能使得key左边的数据全部都小于key,key右边的数据全部都大于key。
然后也还是将key的左序列和右序列再次进行这种单趟排序,如此反复操作下去,直到左右序列只有一个数据,或是左右序列不存在时,便停止操作
代码:
- int PartSort3(int* a, int begin, int end)
- {
- int key = a[begin];
- int prev = begin;
- int cur = begin + 1;
- while (cur <= end)
- {
- if (a[cur] < key)
- {
- prev++;
- Swap(&a[cur], &a[prev]);
- }
- cur++;
- }
- Swap(&a[begin], &a[prev]);
- return prev;
- }
-
-
- void QuickSort(int* a, int begin, int end)
- {
- if (begin >= end)
- return;
- int keyi=PartSort3(a, begin, end);
- QuickSort(a, begin, keyi - 1);
- QuickSort(a, keyi + 1, end);
- }
思想:
非递归的思想可以借助数据结构栈来实现,我们仍然利用先前所写的partsort函数,三者思路均可。只是在QuickSort函数里面不使用递归。
代码:
- int PartSort1(int* a, int begin, int end)//这里我们利用第一种hoare思路
- {
- int keyi = begin;
- int key = a[begin];
- while (begin < end)
- {
- while (begin < end && a[end] >= key)
- end--;
- while (begin < end && a[begin] <= key)
- begin++;
- Swap(&a[end], &a[begin]);
- }
- Swap(&a[end], &a[keyi]);
- return end;
- }
- void QuickSortNonR(int* a, int begin, int end)
- {
- ST st;//ST是一个栈,建立一个栈
- InitStack(&st);//初始化栈
- PushStack(&st, end);//将右边界入栈
- PushStack(&st, begin);//将左边界入栈
- while (!StackEmpty(&st))//当栈不为空
- {
- int left = StackTop(&st);//栈顶元素为左边界
- PopStack(&st);//弹出栈顶元素
- int right = StackTop(&st);//栈顶元素为右边界
- PopStack(&st);//弹出栈顶元素
- int keyi = PartSort1(a, left, right);//进行一趟排序
- if (right > keyi + 1)
- {
- PushStack(&st, right);//再将右边区间入栈,类比递归的思想
- PushStack(&st, keyi + 1);
- }
- if (left < keyi - 1)
- {
- PushStack(&st, keyi - 1);//再将左边区间入栈
- PushStack(&st, left);
- }
-
- }
- DestroyStack(&st);//销毁栈
- }
- void _MergeSort(int* a, int left, int right, int* tmp)//递归版本
- {
- /*if (left == right)
- return;*/
- if (right - left + 1 <= 10)//最小区间优化
- {
- QuickSort(a, left, right);
- return;
- }
- int mid = (left + right) / 2;//将区间一分为二
- _MergeSort(a, left, mid, tmp);
- _MergeSort(a, mid + 1, right, tmp);
- int start1 = left, end1 = mid;
- int start2 = mid + 1, end2 = right;
- int i = left;
- while (start1 <= end1 && start2 <= end2)
- {
- if (a[start1] <=a[start2])
- tmp[i++] = a[start1++];
- else
- tmp[i++] = a[start2++];
- }
- while (start1 <= end1)
- {
- tmp[i++] = a[start1++];
- }
- while (start2 <= end2)
- {
- tmp[i++] = a[start2++];
- }
- memcpy(a + left, tmp + left, sizeof(int) * (right - left + 1));
- }
-
- void MergeSort(int* a, int n)
- {
- int* tmp = (int*)malloc(sizeof(int) * n);
- _MergeSort(a, 0, n - 1, tmp);
- free(tmp);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。