c语言内部排序实验报告,几种常见内部排序算法分析与实现(C语言描述)

1. 插入排序

1.1 算法思想

插入排序算法的主要思想是:

1) 把要排序的序列分为两部分: 已排序部分(A)和未排序部分(B); 由于已排序部分和未

排序部分有显示的位置分隔, 我们也可以将已排序部分称之为序列的前部分, 将未排

序 部分称之为序列的后部分. 显然在算法开始前, 已排序部分为空, 未排序部分为

整个待排序序列.

2) 从B中取第一个元素(b), 然后从后往前依次从A中取出元素(a)与b比较, 若b

a往后移动一个位置; 否则, 为b找到了其正确位置(a的位置的下一个位置), 把b放入

该位置(记住: A是已经排序好的).

3) 对A增加一个元素: b, 对B减少一个元素: b.

4) 重复 2 - 3 步骤, 直至B为空.

1.2 实现

[cpp] view plain

copy

// #c---

/*==========================================================================*

* @Description:

* 插入排序

*

* @Param base

* @Param nmemb

* @Param size

* @Param compar

*==========================================================================*/

void Sort_insertSort(void *base, size_t nmemb, size_t size,

int(*compar)(const void *, const void *))

{

#define SWAP(a, b, t) ( (t)=(a), (a)=(b), (b)=(t) )

assert(base != NULL && nmemb >= 1 && size >= 1 && compar != NULL);

char *i, *j, t, *b, *e;

char *bot = (char*)base;

char *top = bot + nmemb * size;

for ( i = bot + size; i < top; i += size )

{

for ( j = i; (j-=size) >= bot && compar(i, j) < 0; )

{ }

if ( i != (j+=size) )

{

for ( b = j, e = i-1; b < e; b++, e-- )

SWAP(*b, *e, t);

for ( b = i, e = i+size-1; b < e; b++, e-- )

SWAP(*b, *e, t);

for ( b = j, e = i+size-1; b < e; b++, e-- )

SWAP(*b, *e, t);

}

}

#undef SWAP

}

// #c---end

1.3 算法复杂度分析

从插入排序的算法思想中, 我们很容易得知其空间复杂度为 O(1), 时间复杂度为 O(N^2).

2. 选择排序

2.1 算法思想

选择排序算法的主要思想是:

1) 把要排序的序列分为两部分: 已排序部分(A)和未排序部分(B); 由于已排序部分和未

排序部分有显示的位置分隔, 我们也可以将已排序部分称之为序列的前部分, 将未排

序部分称之为序列的后部分. 显然在算法开始前, 已排序部分为空, 未排序部分为整

个待排序序列.

2) 遍历B中的每一个元素, 找到B中的最小元素(b), 把b与A之后的那个元素交换.

3) 对A增加一个元素: b, 对B减少一个元素: b.

4) 重复 2 - 3 步骤, 直至B为空.

2.2 实现

[cpp] view plain

copy

// #c---

/*==========================================================================*

* @Description:

* 选择排序

*

* @Param base

* @Param nmemb

* @Param size

* @Param compar

*

*==========================================================================*/

void Sort_selectSort(void *base, size_t nmemb, size_t size,

int(*compar)(const void *, const void *))

{

#define SWAP(a, b, t) ( (t)=(a), (a)=(b), (b)=(t) )

assert(base != NULL && nmemb >= 1 && size >= 1 && compar != NULL);

int s;

char t, *i, *j, *min;

char *left = base;

char *right = left + (nmemb - 1) * size;

for ( i = left; i <= right - size; i += size )

{

min = i;

for ( j = i + size; j <= right; j += size )

{

if ( compar(j, min) < 0 )

min = j;

}

if ( i != min )

for ( s = 0; s < size; s++ )

SWAP(*(i+s), *(min+s), t);

}

#undef SWAP

}

// #c---end

2.3 算法复杂度分析

选择排序的空间复杂度为 O(1), 时间复杂度为 O(N^2).

3. 冒泡排序

3.1 算法思想

冒泡排序算法的主要思想是:

1) 把要排序的序列分为两部分: 已排序部分(A)和未排序部分(B); 由于已排序部分和未排

序部分有显示的位置分隔, 我们也可以将已排序部分称之为序列的前部分, 将未排序

部分称之为序列的后部分. 显然在算法开始前, 已排序部分为空, 未排序部分为整个

待排序序列.

2) 对B进行从后往前遍历, 取所有相邻的两个元素对(b1和b2, b1较靠后, b2较靠前)作比

较; 若b1

置到了正确的位置上.

3) 对A增加一个元素: b, 对B减少一个元素: b.

4) 重复 2 - 3 步骤, 直至B为空.

3.2 实现

[cpp] view plain

copy

// #c---

/*==========================================================================*

* @Description:

* 冒泡排序

*

* @Param base

* @Param nmemb

* @Param size

* @Param compar

*

*==========================================================================*/

void Sort_bubbleSort(void *base, size_t nmemb, size_t size,

int(*compar)(const void *, const void *))

{

#define SWAP(a, b, t) ( (t)=(a), (a)=(b), (b)=(t) )

assert(base != NULL && nmemb >= 1 && size >= 1 && compar != NULL);

int s, isSwap;

char t, *i, *j;

char *left = base;

char *right = base + (nmemb - 1) * size;

for ( i = left; i < right; i += size )

{

isSwap = 0;

for ( j = right; j > i; j -= size )

{

if ( compar(j, j-size) < 0 )

{

isSwap = 1;

for ( s = 0; s < size; s++ )

SWAP(*(j+s), *(j-size+s), t);

}

}

if ( isSwap == 0 )

break;

}

#undef SWAP

}

// #c---end

3.3 算法复杂度分析

冒泡排序的空间复杂度为 O(1), 时间复杂度为 O(N^2).

4. 合并排序

4.1 算法思想

1) 将序列分为两个子序列.

2) 对两个子序列递归地进行合并排序.

3) 把此两个子序列(已排序)合并为一个有序序列.

4.2 实现

[cpp] view plain

copy

// #c---

/*==========================================================================*

* @Description:

* 合并排序之合并例程

*

* @Param left

* @Param center

* @Param right

* @Param size

* @Param compar

* @Param tmparray

*

*==========================================================================*/

static void SortST_memge(char *left, char *center, char *right, int size,

int(*compar)(const void *, const void *), char *tmparray)

{

#define COPY_SIZE(d, s) \

do { \

for ( i = 0; i < size; i++ ) \

*((d) + i) = *((s) + i); \

} while ( 0 )

int i;

char *Lright = center;

char *Rright = right;

char *Lpcur = left;

char *Rpcur = center + size;

char *Tpcur = tmparray;

for ( ; Lpcur <= Lright && Rpcur <= Rright; Tpcur += size )

{

if ( compar(Lpcur, Rpcur) < 0 )

{

COPY_SIZE(Tpcur, Lpcur);

Lpcur += size;

}

else

{

COPY_SIZE(Tpcur, Rpcur);

Rpcur += size;

}

}

for ( ; Lpcur <= Lright; Lpcur += size, Tpcur += size )

COPY_SIZE(Tpcur, Lpcur);

for ( ; Rpcur <= Rright; Rpcur += size, Tpcur += size )

COPY_SIZE(Tpcur, Rpcur);

for ( Lpcur = left; Lpcur <= right; Lpcur += size, tmparray += size )

COPY_SIZE(Lpcur, tmparray);

#undef COPY_SIZE

}

/*==========================================================================*

* @Description:

* 合并排序

*

* @Param left

* @Param right

* @Param size

* @Param compar

* @Param tmparray

*

*==========================================================================*/

static void Sort_mergeSort_priv(char *left, char *right, int size,

int(*compar)(const void *, const void *), char *tmparray)

{

if ( left < right )

{

char *center = left + ((right - left) / size / 2) * size;

Sort_mergeSort_priv(left, center, size, compar, tmparray);

Sort_mergeSort_priv(center + size, right, size, compar, tmparray);

SortST_memge(left, center, right, size, compar, tmparray);

}

}

/*==========================================================================*

* @Description:

* 合并排序驱动例程

*

* @Param base

* @Param nmemb

* @Param size

* @Param compar

*

*==========================================================================*/

void Sort_mergeSort(void *base, size_t nmemb, size_t size,

int(*compar)(const void *, const void *))

{

assert(base != NULL && nmemb >= 1 && size >= 1 && compar != NULL);

char *left = base;

char *right = base + (nmemb - 1) * size;

char *tmparray;

tmparray = malloc(nmemb * size);

if ( tmparray == NULL )

return;

Sort_mergeSort_priv(left, right, size, compar, tmparray);

free(tmparray);

}

// #c---end

4.3 算法复杂度分析

归并排序算法是运用分治思想的典范, 其空间复杂度为 O(N), 时间复杂度为 O(NlogN).

5. 快速排序

5.1 算法思想

1) 从输入序列中任意选取一个元素(k)作枢纽元;

2) 遍历整个序列, 对于小于等于k的元素放在左边(L), 对于大于k的元素放在右边(R);

3) 对子序列L和R递归地进行快速排序; 直到序列中只有一个若零个元素, 退出递归.

5.2 实现

[cpp] view plain

copy

// #c---

/*==========================================================================*

* @Description:

* 取三者间的中间值

*

* @Param left

* @Param right

* @Param size

* @Param compar

*

* @Returns:

*==========================================================================*/

static char* Sort_median3(char *left, char *right, int size,

int(*compar)(const void *, const void *))

{

#define SWAP(a, b, t) ( (t)=(a), (a)=(b), (b)=(t) )

int s;

char t;

// char *center = left + (right - left) / 2; // 错误!!

// 每一步计算都必须取整! 才不至于最后的结果位于字节内!

char *center = left + (((right - left) / size) / 2) * size;

if ( compar(left, center) > 0 )

for ( s = 0; s < size; s++ )

SWAP(*(left+s), *(center+s), t);

if ( compar(left, right) > 0 )

for ( s = 0; s < size; s++ )

SWAP(*(left+s), *(right+s), t);

if ( compar(center, right) > 0 )

for ( s = 0; s < size; s++ )

SWAP(*(center+s), *(right+s), t);

for ( s = 0; s < size; s++ )

SWAP(*(center+s), *(right-size+s), t);

return right - size;

#undef SWAP

}

/*==========================================================================*

* @Description:

* 快速排序

*

* @Param left

* @Param right

* @Param size

* @Param compar

*==========================================================================*/

static void Sort_quicklySort_priv(char *left, char *right, int size,

int(*compar)(const void *, const void *))

{

#define SWAP(a, b, t) ( (t)=(a), (a)=(b), (b)=(t) )

int s;

char t, *i, *j, *pivot;

if ( left + SORT_CUTOFF * size <= right )

{

pivot = Sort_median3(left, right, size, compar);

i = left;

j = right - size;

for ( ; ; )

{

for ( i += size; compar(i, pivot) < 0; i += size ) { }

for ( j -= size; compar(j, pivot) > 0; j -= size ) { }

if ( i < j )

{

for ( s = 0; s < size; s++ )

SWAP(*(i+s), *(j+s), t);

}

else

break;

}

for ( s = 0; s < size; s++ )

SWAP(*(i+s), *(right-size+s), t);

Sort_quicklySort_priv(left, i - size, size, compar);

Sort_quicklySort_priv(i + size, right, size, compar);

}

else

Sort_insertSort(left, (right-left)/size + 1, size, compar);

#undef SWAP

}

/*==========================================================================*

* @Description:

* 快速排序驱动例程

*

* @Param base

* @Param nmemb

* @Param size

* @Param compar

*==========================================================================*/

void Sort_quicklySort(void *base, size_t nmemb, size_t size,

int(*compar)(const void *, const void *))

{

assert(base != NULL && nmemb >= 1 && size >= 1 && compar != NULL);

if ( nmemb <= 1 )

return;

if ( nmemb >= SORT_CUTOFF )

Sort_quicklySort_priv(base, base + (nmemb-1)*size, size, compar);

else

Sort_insertSort(base, nmemb, size, compar);

}

// #c---end

5.3 算法复杂度分析

快速排序算法也是运用分治思想, 其空间复杂度为 O(1), 时间复杂度为 O(NlogN).

本文出自:亿恩科技【www.enkj.com】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值