Chapter 7 Sorting

冒泡排序

#include <stdio.h>

typedef int ElementType;
void BubbleSort(ElementType A[], int N)
{
	int i, j, Tmp;
	for (i = 0; i < N - 1; i++)
	{
		for (j = 0; j < N - 1 - i; j++)
		{
			if (A[j] > A[j + 1])
			{
				Tmp = A[j];
				A[j] = A[j + 1];
				A[j + 1] = Tmp;
			}
		}
	}
}
/*
  最好情况:顺序O(N);
  最坏情况:逆序O(N2);
  稳定性:稳定;
*/

选择排序

#include <stdio.h>

typedef int ElementType;

void Swap(ElementType *a, ElementType *b)
{
	ElementType Tmp;
	Tmp = *a;
	*a = *b;
	*b = Tmp;
}
void CelecteSort(ElementType A[], int N)
{
	int i, j;
	for (i = 0; i < N; i++)
	{
		int Min = i;
		for (j = i + 1; j < N; j++)
		{
			if (A[j] < A[Min])
				Min = j;
		}
		Swap(&A[Min], &A[i]);
	}
}

/*
  时间复杂度:O(N^2);
  稳定性:不稳定
*/

插入排序

#include <stdio.h>

typedef int ElementType;
void InsertionSort(ElementType A[], int N)
{
	int j, P;
	ElementType Tmp;
	for (P = 1; P < N; P++)
	{
		Tmp = A[P];
		for (j = P; j > 0 && A[j - 1] > Tmp; j--)
			A[j] = A[j - 1];
		A[j] = Tmp;
	}
}
/*
  最好情况:O(N)
  最差情况:O(N2)
  稳定性:稳定
*/

堆排序

/*
①将关键字构造成树。
②下滤形成初始堆。
*/
#include <stdio.h>
#include <stdlib.h>
#define LeftChild(i)(2 * (i) + 1)

typedef int ElementType;
void Swap(ElementType *a, ElementType *b)
{
	ElementType Tmp;
	Tmp = *a;
	*a = *b;
	*b = Tmp;
}

void PercDown(ElementType A[], int i, int N)
{
	int Child;
	ElementType Tmp;

	for (Tmp = A[i]; LeftChild(i) < N; i = Child)           //取出根节点存放的值
	{
		Child = LeftChild(i);                           //得到左孩子的值
		if (Child != N - 1 && A[Child + 1] > A[Child])  //取左右孩子中较大的
			Child++; 
		if (Tmp < A[Child])      //下滤
			A[i] = A[Child];
		else                     //找到合适位置            
			break;
	}
	A[i] = Tmp;                      //赋值
}

void HeapSort(ElementType A[], int N)
{
	int i;
	ElementType Tmp;
	for (i = N / 2; i >= 0; i--)     //从最后一个不为叶子的节点开始下滤
		PercDown(A, i, N);
	for (i = N - 1; i > 0; i--)   
	{
		Swap(&A[0], &A[i]);      //“删除”最大根
		PercDown(A, 0, i);       //调整大根堆
	}
}

/*
  时间复杂度:O(NlogN)
  稳定性:不稳定
*/

归并排序

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;

//将有序的A[Lpos]~A[Rpos-1]和A[Rpos]~A[RightEnd]归并成一个有序序列
void Merge(ElementType A[], ElementType TmpArray[], int Lpos, int Rpos, int RightEnd)
{
	// Lpos = 左边起始位置, Rpos = 右边起始位置, RightEnd = 右边终点位置
	int i, LeftEnd, NumElements, TmpPos;
	LeftEnd = Rpos - 1;                   //左边终点位置
	TmpPos = Lpos;                        //有序序列的起始位置
	NumElements = RightEnd - Lpos + 1;

	while (Lpos <= LeftEnd && Rpos <= RightEnd)              
	{
		if (A[Lpos] <= A[Rpos])
			TmpArray[TmpPos++] = A[Lpos++];//将左边元素复制到TmpA
		else
			TmpArray[TmpPos++] = A[Rpos++];//将右边元素复制到TmpA
	}

	while (Lpos <= LeftEnd)                                  
		TmpArray[TmpPos++] = A[Lpos++];  //直接复制左边剩下的
	while (Rpos <= RightEnd)                                 
		TmpArray[TmpPos++] = A[Rpos++];  //直接复制右边剩下的

	for (i = 0; i < NumElements; i++, RightEnd--)            
		A[RightEnd] = TmpArray[RightEnd]; //将有序的TmpA[]复制回A[] 
}

//递归实现
void MSort_Recursion(ElementType A[], ElementType TmpArray[], int Left, int Right)
{
	int Center;
	if (Left < Right)
	{
		Center = (Left + Right) / 2;                  
		MSort_Recursion(A, TmpArray, Left, Center);            //递归解决左边
		MSort_Recursion(A, TmpArray, Center + 1, Right);       //递归解决右边
		Merge(A, TmpArray, Left, Center + 1, Right); //合并两段有序序列
	}
}

void MergeSort_Recursion(ElementType A[], int N)
{
	ElementType  *TmpArray;
	TmpArray = (ElementType*)malloc(sizeof(ElementType) * N);  
	if (TmpArray != NULL)
	{
		MSort_Recursion(A, TmpArray, 0, N - 1);
		free(TmpArray);
	}
	else printf("空间不足");
}

//非递归实现
//两两归并相邻有序子列 
void Merge_NonRecursive(ElementType A[], ElementType TmpArray[], int N, int Length)
{ 
	//length = 当前有序子列的长度
	int i, j;

	for (i = 0; i <= N - 2 * Length; i += 2 * Length) //归并到倒数第二对子列
		Merge(A, TmpArray, i, i + Length, i + 2 * Length - 1);
	if (i + Length < N)                               //归并最后2个子列(1对+1个)
		Merge(A, TmpArray, i, i + Length, N - 1);
	else                                              //最后只剩1个子列(0对+1个),直接赋给TmpA[]
		for (j = i; j < N; j++) 
			TmpArray[j] = A[j];
}

void MergeSort_NonRecursive(ElementType A[], int N)
{
	int Length;
	ElementType *TmpArray;

	Length = 1;       //初始化子序列长度
	TmpArray = (ElementType*)malloc(N * sizeof(ElementType));
	if (TmpArray != NULL) {
		while (Length < N) { 
			Merge_NonRecursive(A, TmpArray, N, Length);
			Length *= 2;
			Merge_NonRecursive(TmpArray, A, N, Length);
			Length *= 2;
		}             //两次归并,保证出循环时,排序后的结果在A[]中
		free(TmpArray);
	}
	else printf("空间不足");
}

/*
  时间复杂度:O(NlogN)
  稳定性:稳定
*/

希尔排序

#include <stdio.h>
#include <math.h>

typedef int ElementType;

/*
  原始希尔排序
  增量元素不互质,则小增量可能根本不起作用
 */
void ShellSort0(ElementType A[], int N)
{
	int i, j, Increment;
	ElementType Tmp;
	for(Increment = N / 2;Increment > 0;Increment /= 2)
	{
		for (i = Increment; i < N; i++)            //插入排序
		{
			Tmp = A[i];
			for (j = i; j >= Increment; j -= Increment)
				if (Tmp < A[j - Increment])
					A[j] = A[j - Increment];
				else
					
					break;
			A[j] = Tmp;
		}
	}
}

/*Hibbard增量序列  
  Dk = 2^k - 1 —— 相邻元素互质
  {1,3,7,15,31,...}
*/
double log2(double input)
{
	return log(input) / log(2);
}

void ShellSort1(ElementType A[], int N)
{
	int i, j, k, Round, Increment;
	ElementType Tmp;
	for (Round = (int)log2(N); Round > 0; Round--)
	{
		Increment = (int)pow(2, Round) - 1;                //根据公式,计算Hibbard增量
		for (i = Increment; i < N; i++)                    //插入排序
		{
			Tmp = A[i];
			for (j = i; j >= Increment; j -= Increment)
				if (Tmp < A[j - Increment])
					A[j] = A[j - Increment];
				else

					break;
			A[j] = Tmp;
		}
	}
}

/*Sedgewick增量序列
  9 * 4^i - 9 * 2^i + 1 或 4^i - 3 * 2^i - 1
  {1,5,19,41,109,...}
*/
void ShellSort2(ElementType A[], int N)
{
	int i, j, k, Increment;
	ElementType Tmp;
	int Sedgewick[] = { 929, 505, 209, 109, 41, 19, 5, 1, 0 };  // 这里只列出一小部分增量

	for (k = 0; Sedgewick[k] >= N; k++)
		;                               // 初始的增量Sedgewick[Si]不能超过待排序列长度 
	for (Increment = Sedgewick[k]; Increment > 0; Increment = Sedgewick[++k])
	{
		for (i = Increment; i < N; i++)                    //插入排序
		{
			Tmp = A[i];
			for (j = i; j >= Increment; j -= Increment)
				if (Tmp < A[j - Increment])
					A[j] = A[j - Increment];
				else

					break;
			A[j] = Tmp;
		}
	}
}


/*
  时间复杂度:O(N^d),视增量的选择而定
  稳定性:不稳定
*/

快速排序

/*①选择基准(使A[Left] < R[Center] < A[Right],交换A[Center],A[Right-1]。
  ②令 i 从 0 开始向后,j 从 Right - 1 开始向前。
  ③当 A[i] 大于等于基准时,停下,当 A[j] 小于等于基准时,停下。
  ④当 i,j 都停下时,交换指向的元素。
  ⑤当 i > j,退出循环,将基准与 i 指向的元素交换。*/

#include <stdio.h>
#include <stdlib.h>
#define Cutoff 3

typedef int ElementType;
void Swap(ElementType *a, ElementType *b)
{
	ElementType Tmp;
	Tmp = *a;
	*a = *b;
	*b = Tmp;
}

void InsertionSort(ElementType A[], int N)
{
	int j, P;
	ElementType Tmp;
	for (P = 1; P < N; P++)
	{
		Tmp = A[P];
		for (j = P; j > 0 && A[j - 1] > Tmp; j--)
			A[j] = A[j - 1];
		A[j] = Tmp;
	}
}

ElementType Median3(ElementType A[], int Left, int Right)
{
	int Center = (Left + Right) / 2;

	if (A[Left] > A[Center])
		Swap(&A[Left], &A[Center]);
	if (A[Left] > A[Right])
		Swap(&A[Left], &A[Right]);
	if (A[Center] > A[Right])
		Swap(&A[Center], &A[Right]);
	//此时A[Left] <= A[Center] <= A[Right]
	
	Swap(&A[Center], &A[Right - 1]);     //将基准Pivot藏到右边;
	//此时A[Right]一定大于A[Right-1],接下来只需要考虑A[Left+1] … A[Right-2]
	return A[Right - 1];      //返回基准
}

void QSort(ElementType A[], int Left, int Right)
{
	int i, j;
	ElementType Pivot;

	if (Right - Left >= Cutoff)      //如果序列元素大于阈值,进入快速排序
	{
		Pivot = Median3(A, Left, Right);
		i = Left;
		j = Right - 1;
		for (; ;)               //将序列中比基准小的移到基准左边,大的移到右边
		{
			while (A[++i] < Pivot) {}   //大于等于基准时退出循环
			while (A[--j] > Pivot) {}   //小于等于基准时退出循环
			if (i < j)
				Swap(&A[i], &A[j]);
			else
				break;
		}
		Swap(&A[i], &A[Right - 1]);//将基准换到正确的位置

		QSort(A, Left, i - 1);     //递归解决左边
		QSort(A, i + 1, Right);    //递归解决右边
	}
	else
		InsertionSort(A + Left, Right - Left + 1); //元素太少,用简单排序
}

void QuickSort(ElementType A[], int N)
{
	QSort(A, 0, N - 1);
}

/*
时间复杂度:O(NlogN)
稳定性:不稳定
*/

基数排序

#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
/* 基数排序 - 次位优先 */
 
/* 假设元素最多有MaxDigit个关键字,基数全是同样的Radix */
#define MaxDigit 4
#define Radix 10
 
/* 桶元素结点 */
typedef struct Node *PtrToNode;
struct Node {
    int key;
    PtrToNode next;
};
 
/* 桶头结点 */
struct HeadNode {
    PtrToNode head, tail;
};
typedef struct HeadNode Bucket[Radix];
  
int GetDigit ( int X, int D )
{ /* 默认次位D=1, 主位D<=MaxDigit */
    int d, i;
     
    for (i=1; i<=D; i++) {
        d = X % Radix;
        X /= Radix;
    }
    return d;
}
 
void LSDRadixSort( ElementType A[], int N )
{ /* 基数排序 - 次位优先 */
     int D, Di, i;
     Bucket B;
     PtrToNode tmp, p, List = NULL; 
      
     for (i=0; i<Radix; i++) /* 初始化每个桶为空链表 */
         B[i].head = B[i].tail = NULL;
     for (i=0; i<N; i++) { /* 将原始序列逆序存入初始链表List */
         tmp = (PtrToNode)malloc(sizeof(struct Node));
         tmp->key = A[i];
         tmp->next = List;
         List = tmp;
     }
     /* 下面开始排序 */ 
     for (D=1; D<=MaxDigit; D++) { /* 对数据的每一位循环处理 */
         /* 下面是分配的过程 */
         p = List;
         while (p) {
             Di = GetDigit(p->key, D); /* 获得当前元素的当前位数字 */
             /* 从List中摘除 */
             tmp = p; p = p->next;
             /* 插入B[Di]号桶尾 */
             tmp->next = NULL;
             if (B[Di].head == NULL)
                 B[Di].head = B[Di].tail = tmp;
             else {
                 B[Di].tail->next = tmp;
                 B[Di].tail = tmp;
             }
         }
         /* 下面是收集的过程 */
         List = NULL; 
         for (Di=Radix-1; Di>=0; Di--) { /* 将每个桶的元素顺序收集入List */
             if (B[Di].head) { /* 如果桶不为空 */
                 /* 整桶插入List表头 */
                 B[Di].tail->next = List;
                 List = B[Di].head;
                 B[Di].head = B[Di].tail = NULL; /* 清空桶 */
             }
         }
     }
     /* 将List倒入A[]并释放空间 */
     for (i=0; i<N; i++) {
        tmp = List;
        List = List->next;
        A[i] = tmp->key;
        free(tmp);
     } 
}


/* 基数排序 - 主位优先 */
 
/* 假设元素最多有MaxDigit个关键字,基数全是同样的Radix */
 
#define MaxDigit 4
#define Radix 10
 
/* 桶元素结点 */
typedef struct Node *PtrToNode;
struct Node{
    int key;
    PtrToNode next;
};
 
/* 桶头结点 */
struct HeadNode {
    PtrToNode head, tail;
};
typedef struct HeadNode Bucket[Radix];
  
int GetDigit ( int X, int D )
{ /* 默认次位D=1, 主位D<=MaxDigit */
    int d, i;
     
    for (i=1; i<=D; i++) {
        d = X%Radix;
        X /= Radix;
    }
    return d;
}
 
void MSD( ElementType A[], int L, int R, int D )
{ /* 核心递归函数: 对A[L]...A[R]的第D位数进行排序 */
     int Di, i, j;
     Bucket B;
     PtrToNode tmp, p, List = NULL; 
     if (D==0) return; /* 递归终止条件 */
      
     for (i=0; i<Radix; i++) /* 初始化每个桶为空链表 */
         B[i].head = B[i].tail = NULL;
     for (i=L; i<=R; i++) { /* 将原始序列逆序存入初始链表List */
         tmp = (PtrToNode)malloc(sizeof(struct Node));
         tmp->key = A[i];
         tmp->next = List;
         List = tmp;
     }
     /* 下面是分配的过程 */
     p = List;
     while (p) {
         Di = GetDigit(p->key, D); /* 获得当前元素的当前位数字 */
         /* 从List中摘除 */
         tmp = p; p = p->next;
         /* 插入B[Di]号桶 */
         if (B[Di].head == NULL) B[Di].tail = tmp;
         tmp->next = B[Di].head;
         B[Di].head = tmp;
     }
     /* 下面是收集的过程 */
     i = j = L; /* i, j记录当前要处理的A[]的左右端下标 */
     for (Di=0; Di<Radix; Di++) { /* 对于每个桶 */
         if (B[Di].head) { /* 将非空的桶整桶倒入A[], 递归排序 */
             p = B[Di].head;
             while (p) {
                 tmp = p;
                 p = p->next;
                 A[j++] = tmp->key;
                 free(tmp);
             }
             /* 递归对该桶数据排序, 位数减1 */
             MSD(A, i, j-1, D-1);
             i = j; /* 为下一个桶对应的A[]左端 */
         } 
     } 
}
 
void MSDRadixSort( ElementType A[], int N )
{ /* 统一接口 */
    MSD(A, 0, N-1, MaxDigit); 
}



/*时间复杂度:O(P(N+B))
  稳定性:稳定
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值