现在的位置: 首页 > 综合 > 正文

编程珠玑笔记–排序

2017年10月06日 ⁄ 综合 ⁄ 共 2293字 ⁄ 字号 评论关闭

首先来个插入排序

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include
<
stdio.h>
 
void
swap(int *x, int *y)
{
    int
t = *x;
    *x
= *y;
    *y
= t;
}
void
insert_sort(int *x, int length)
{
    int
i, j;
    for
(i = 1; i <
length;
i++)
        for
(
j

=
i;
j > 0 && x[j-1] > x[j]; j--)
            swap(&x[j-1],
&x[j]);
}
 
int
main(void)
{
     
    int
i, a[] = {42, 20, 17, 13, 28, 14, 23, 15};
    insert_sort(a,
8);
    for
(i = 0; i < 8;i++)
       printf("%4d",
a[i]);    
    return
0;
}

在第二个for循环中,总是给t赋予相同值x[i],可以将其移出第二个for循环

?
1
2
3
4
5
6
7
8
9
10
11
void
insert_sort(int *x, int length)
{
    int
i, j;
    for
(i = 1; i <
length;
i++)
    {
        int
t

=
x[i];
        for
(
j

=
i;
j > 0 && x[j-1] > t; j--)
            x[j]
= x[j-1];
        x[j]
= t;
    }
}

一种简单的快速排序

排序数组时,将数组不停分成两个小部分,进行递归排序,分别用l和u表示数组排序部分的下界和上界,递归结束条件是待排序部分的元素个数小于2.

然后围绕某一值t对数组进行划分,重新组织x[a….b],并计算中间元素的下标m,使得所有<t在m左,所有>t在m右

|a      <t         |m       >= t     |i            ?未处理部分            b|

?
1
2
3
4
m
= a -1;
for
i = [a, b]
    if
x[i] < t
        swap(++m,
i);
?
1
2
3
4
void
q_sort(int l, int u)
{
    if
(l >= u)
        return
;
?
1
m
= l;
?
1
for
(int i = l +1; i <= u; i++)
?
1
if
(x[i] < x[l])
?
1
swap(++m,
i);
?
1
2
3
4
       swap(m,
l);
    qsort(l,
p -1);
    qsort(p
+ 1, u);
}

 

从右侧划分,完整代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void
qsort2(int l, int u)
{
    if
(l >= u)
        return;
    m
= i = u + 1;
    do
    {
      while
(x[--i] < x[l]) ;   
         swap(i,
--m); 
    }
        while
(i != l)
    qsort2(l,
m - 1);
    qsort2(m
+ 1, u);
}

当元素相同时,为最坏情况o(n*n),使用双向划分可解决问题,变为o(nlog(n))

?
1
主循环中有两个循环,第一个内循环将i向右移过小元素,遇到大元素停止;第二个内循环向左移过大元素,遇到小元素停止。
?
1
主循环测试这两个下标若交叉,则交换它们的值。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void
qsort3(int l, int u)
{
    if
(l >= u)
        return
;
    int
i = l, j = u + 1, t = x[l];
    while
(1)
    {
        while
(x[j] > t) j--;
        while
(i <= u && x[i] &l
t;
t) i++;
        if
(i > j)
            break;
        swap(i,
j);
    }
    swap(l,
j);
    qsort3(l,
j - 1);
    qsort3(j
+ 1, u);
}
?
1
  

以上都是按照第一个元素进行划分,随机选择划分元素可得到更好的性能 swap(l, randint(l, u));.

?
1
2
3
4
5
6
7
8
9
int
bigrand()
{
    return
RAND_MAX*rand() + rand();
}
 
int
randint(int l, int u)
{
    return
l + bigrand() % (u - l + 1);
}

对于任意n元输入数组,快速排序时间都正比于nlogn。

快速排序会花费大量时间来排序很小数组,如果用插入排序累排序小数组,程序速会更快。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void
qsort4(int l, int u)
{
    if
(u - l <
cutoff)
        return;
    swap(l.
randint(l, u));
    int
t

=
x[l],
i

=
l,
j

=
u

+ 1;
    for
(;;)
    {
        while
(i <= u && x[i] < t) i++;
        while
(x[j] > t) j--;
        if
(x > j)
            break;
        swap(i,
j);
    }
    swap(j,
l);
    qsort4(l,
j - 1);
    qsrt4(j
+ 1, u);
}
 
void
test()
{
      qsort4(0,
length - 1)
      insert_sort(x,
length);
}

抱歉!评论已关闭.