2 1 1 2 4 2 4 2 开始:1 和2 比,1比2小,浮上,然后1跟4比,再1跟3比,这样结构就变为1,3,4,2。最小的位置确定了,然后我们确定第二小的,同理2 vs 4, 2 vs 3 得到2, 再确定第3小数据,3 vs 4得到3,最后就是4为最大的数据,我们冒泡就排好了。 注:这里红色的1,2是前一次比较1 vs 2交换的结构。后面也一样。 大概思路就这样了,奉上源代码: #include
//冒泡排序, pnData要排序的数据, nLen数据的个数 int BubbleSort(int* pnData, int nLen) {
bool isOk = false; //设置排序是否结束的哨兵 //i从[0,nLen-1)开始冒泡,确定第i个元素 for (int i = 0; i < nLen - 1 && !isOk; ++i) {
isOk = true; //假定排序成功
//从[nLen - 1, i)检查是否比上面一个小,把小的冒泡浮上去 for (int j = nLen- 1; j > i; --j) {
if (pnData[j] < pnData[j - 1]) //如果下面的比上面小,交换 {
int nTemp = pnData[j]; pnData[j] = pnData[j - 1]; pnData[j - 1] = nTemp; isOk = false; } } }
return 1; }
int main() {
int nData[10] = {4,10,9,8,7,6,5,4,3,2}; //创建10个数据,测试 BubbleSort(nData, 10); //调用冒泡排序 for (int i = 0; i < 10; ++i) {
printf(\ }
printf(\
system(\ return 0; }
选择排序
选择排序和冒泡排序思路上有一点相似,都是先确定最小元素,再确定第二笑元素,最后确定最大元素。他的主要流程如下:
1.加入一个数组A = {5,3,6,2,4,7},我们对他进行排序
2.确定最小的元素放在A[0]位置,我们怎么确定呢,首先默认最小元素为5,他的索引为0,然后用它跟3比较,比他打,则认为最小元素为3,他的索引为1,然后用3跟6比,发现比他小,最小元素还是3,然后跟2比,最小元素变成了2,索引为3,然后跟4比,跟7比。当比较结束之后,最小元素也尘埃落定了。就是2,索引为3,然后我们把他放在A[0]处。为了使A[0]原有数据部丢失,我们使A[0](要放的位置) 与A[3](最小数据的位置)交换。这样就不可以了吗?
3.然后我们在来找第二小元素,放在A[1],第三小元素,放在A[2]。。当寻找完毕,我们排序也就结束了。
4.不过,在找的时候要注意其实位置,不能在找A[2]的时候,还用A[2]的数据跟已经排好的A[0],A[1]比,一定要跟还没有确定位置的元素比。还有一个技巧就是我们不能每次都存元素值和索引,我们只存索引就可以了,通过索引就能找到元素了。
5.他和冒泡的相似和区别,冒泡和他最大的区别是他发现比他小就交换,把小的放上面,而选择是选择到最小的在直接放在确定的位置。选择也是稳定的排序。 基本思路就这样了,奉上源代码: #include
//选择排序, pnData要排序的数据, nLen数据的个数 int SelectSort(int* pnData, int nLen) {
//i从[0,nLen-1)开始选择,确定第i个元素 for (int i = 0; i < nLen - 1; ++i) {
int nIndex = i;
//遍历剩余数据,选择出当前最小的数据 for (int j = i + 1; j < nLen; ++j) {
if (pnData[j] < pnData[nIndex]) {
nIndex = j; } }
//如果当前最小数据索引不是i,也就是说排在i位置的数据在nIndex处 if (nIndex != i) {
//交换数据,确定i位置的数据。 int nTemp = pnData[i];
pnData[i] = pnData[nIndex]; pnData[nIndex] = nTemp; } }
return 1; }
int main() {
int nData[10] = {4,10,9,8,7,6,5,4,3,2}; //创建10个数据,测试 SelectSort(nData, 10); //调用选择排序 for (int i = 0; i < 10; ++i) {
printf(\ }
printf(\
system(\ return 0; }
希尔排序
希尔排序,他的主要思想借用了合并排序的思想。不过他不是左边一半右边一半,而是按照步长来分,随着步长减少,分成的组也越少。然后进行各组的插入排序。主要思路就是这样。 #include
int SortGroup(int* pnData, int nLen, int nBegin,int nStep) {
for (int i = nBegin + nStep; i < nLen; i += nStep) {
//寻找i元素的位置,
for (int j = nBegin; j < i; j+= nStep) {
//如果比他小,则这里就是他的位置了 if (pnData[i] < pnData[j]) {
int nTemp = pnData[i];
for (int k = i; k > j; k -= nStep) {
pnData[k] = pnData[k - nStep]; }
pnData[j] = nTemp; } } }
return 1; }
//希尔排序, pnData要排序的数据, nLen数据的个数 int ShellSort(int* pnData, int nLen)
{
//以nStep分组,nStep每次减为原来的一半。 for (int nStep = nLen / 2; nStep > 0; nStep /= 2) {
//对每个组进行排序
for (int i = 0 ;i < nStep; ++i) {
SortGroup(pnData, nLen, i, nStep); } }
return 1; }
int main() {
int nData[10] = {4,10,9,8,7,6,5,4,3,2}; //创建10个数据,测试 ShellSort(nData, 10); //调用希尔排序 for (int i = 0; i < 10; ++i) {
printf(\ }
printf(\
system(\ return 0; }
合并排序合并排序的主要思想是:把两个已经排序好的序列进行合并,成为一个排序好的 序列。例如:13579 2468这两个序列,各自都是排好序的,然后我们进行合并,成为123456789这样一个
排好序的序列。貌似这个跟排序关系不大,因为排序给的是一个乱的序列,而合并是合并的两个已经排序
好的序列。且慢,我们可以把需要排序的数据分解成N个子序列,当分解的子序列所包含数据个数为1的时
候,那么这个序列不久是有序了吗?然后再合并。这个就是有名的”分治。例如321分成3,2,1三个序列,1这个序列是有序的啦。同理2,3都是有序的。然后我们逐一的合并他们。3,2合并为23,
然后在23与1合并为123。哈哈,排序成功。合并排序主要思路就是这样了。
但是,问题又出来了,怎么合并两个有序列呢?我相信我应该理解了数组的存储方式,所以直接用数组说 事啦。。我们先把下标定位到各有序子序列的开始,也把合并之后数组的下标定位到最初。那么下标对应
的位置就是他们当前的最小值了。然后拿他们来比较,把更小的那个放到合并之后数组的下标位置。这样
,合并后数组的第一个元素就是他们的最小值了。接着,控制合并后数组的下标后移一个,把比较时小数
字所在序列对应的下标后移一个。这样。下次比较的时候,他得到就是他的第二小,(第一
下已经合并了
)就是当前最小值了,在于另一个序列的当前最小值比较,用小的一个放到合并后数组的相应位置。依次
类推。接着当数据都合并玩了结束,合并完成。(这样说忒空泛了,云里雾里的,BS一下以前的我。)
1357 2468 来做例子:
(1回合) 1357 2468 00000(合并后数据空)
(2) 357 2468 100000(0表示空) 因为1 < 2所以把1放到合并后位置中了(这里1并不是丢掉了,而是下
标变为指向3了,1是没有写而已。呵呵。理解为数组的下标指向了3) (3) 357 468 120000 因为3 > 2,所以把而放进去 (4) 57 468 123000 同理3 < 4 (5) 57 68 1234000 同理5 > 4 (6) 7 68 1234500 同理5 > 6 (7) 7 8 1234560 同理7 > 6 (8) 0(空了) 8 12345670 同理7 < 8 (9) 0 0 12345678 弄最后一个
当然,这些只是思路。并不是一定一成不变的这样。合并OK,那么我们就可以用合并排序了哦!哈哈。。
不过注意,那个321全部弄成一个单个数字,然后一个一个合并这样来合并似乎不是很好,貌似还有更好
的解决方案。哈哈,对了,就是我先分一半来合并。如果这一半是排好序的,那么合并不久简单了吗?但
是我怎么让一般排好序呢。呵呵简单,我一半在分一半合并排序,在分一半合并排序,直到分到两个都是
1个了,就合并,ok! 例如,81726354: (1)分成9172 6354
(2)把8172 分成 81 和72 把6354分成63和54 (3)81分成8和1,哦能合并了哦。合并为18, 同理72,63,54,也可以分解成单个合并为27,36,45 (4) 现在变为了 18, 27, 36, 45了,这个时侯,18 和27能合并了,合并为1278 同理36,合并为45 3456
(5) 好了最好吧,1278和3456合并为12345678.ok排序成功。
这样把一个问题分解为两个或多个小问题,然后在分解,最后解决小小问题,已达到解决打问题的目的。
1 #include
4 //合并排序的合并程序他合并数组nData中位置为[nP,nM) 和[nM,nR).这个是更接近标准的思路
5 bool MergeStandard(int nData[], int nP, int nM, int nR) 6 {
7 int n1 = nM - nP; //第一个合并数据的长度 8 int n2 = nR - nM; //第二个合并数据的长度
10 int *pnD1 = new int[n1 + 1]; //申请一个保存第一个数据的空间