排序(408)

针对408中考研基础专业课中的排序算法进行学习。
在学习的过程中不断思索,在目前学习的目标与过程中,抽象的元素有哪些?具体的元素有哪些?抽象的部份必须彻底吸收,具体的部份则当作经验,而累积的经验在将来归类整理之后,最终也将化为抽象。
排序算法分为内部排序外部排序
内部排序,针对于数据量相对较小。数据能全都在内存中的排序算法。这类算法要求时间复杂性低,空间复杂性可以高。
外部排序,针对存储在硬盘中的数据,这样的数据量大,内存一次放不下。对时间复杂性要求不高。对空间复杂性要求高。

设原序列 Ri = Rj ,i<j 排序后的位置 Ri 依然 < Rj。则称排序算法是稳定的,否则称为不稳定的。

内部排序

大致分为五大类,插入排序、交换排序、选择排序、归并排序和基数排序
从内部算法工作量上,可以分为三类

  1. 简单的排序算法,其时间复杂度为O( n 2 n^2 n2
  2. 先进的排序算法,其时间复杂度为O(nlogn)
  3. 基数排序,其时间复杂度为O(d*n)

通常,在排序过程中需进行两项基本的操作

  1. 比较两个关键字的大小
  2. 讲记录从一个位置移动到另一个位置

前一个操作对大多数排序算法来说都是必要的,而后一个操作可以通过改变记录的存储方式予以避免。

带排列的记录序列可能有以下三种存储方式。

  1. 在地址连续的一组存储单元上,类似于线性表的顺序存储结构。

在这种存储方式中,记录之间的次序关系由其存储位置决定,则实现排序必须借助移动记录。

  1. 一组待排序记录存放在静态链表中。记录之间的次序关系由指针指示,

实现排序不需要移动记录,仅需修改指针即可。

  1. 待排序记录本身存储在一组地址连续的存储单元内,同时令设一个指示各个记录存储位置的地址向量,

在排序过程中不移动记录本身,而是移动地址向量这些记录的“地址”,在排序结束之后再按照地址向量中的值调整记录的存储位置。

第二种存储方式下实现的排序有称(链)表排序。第三种存储方式下实现的排序叫地址排序。

插入排序

直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录增1的有序表。

void InsertSort(SqList &L){
	// 对顺序表L作直接插入排序
	for(i = 2; i<= L.length; ++i)
		if(LT(L.r[i].key, L.r[i-1].key)){ 	// “<”,需将L.r[i]插入有序子表
			L.r[0] = L.r[i];				// 负责为哨兵
			L.r[i] = L.r[i-1];
			for(j = i-2; LT(L.r[0].key, L.r[j].key); ++j)
				L.r[j+1] = L.r[j];			// 记录后移
			L.r[j+1] = L.r[0];				// 插入到正确位置
		}
} // InsertSort

折半插入排序

希尔排序

void ShellSort(ElemType A[], int n){
	// A[0]是暂存单元,不是哨兵,当j < 0时插入位置已到
	for(dk = n/2, dk>=1;dk=dk/2) 	// 步长变化
		for(i = dk+1; i<n;++1)	
}
快速排序(交换)

以交换进行排序的方法。最简单的就是冒泡排序。

快速排序(Quick Sort)是对气泡排序的一种改进,它的基本思想是,通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对着两部分记录继续进行排序,以达到整个序列有序。

快速排序的思想是基于分治法的:在待排序表L[1…n]中任取一个元素pivot作为枢轴(或基准,通常取首元素),通过一趟排序将待排序表划分为独立的两部分L[1…k-1]和L[k+1…n],使得L[1…k-1]中所有元素小于pivot,L[k+1…n]中所有元素大于等于pivot,则pivot放在了其最终位置L[K]上,这个过程为一趟快速排序(或一次划分)。然后分别递归地对两个子表重复上述过程,直到每部分内只有一个元素或为空为止,即所有元素放在了其最终位置上。

void QuickSort(ElemType A[ ], int low, int high){
	if(low < high){				// 跳出递归的条件
	// partition()  划分操作,将表[LOW..HIGH]划分为满足上述条件的两个子表
		int pivotpos = partition(A, low, high);	// 划分
		QuickSort(A, low, pivotpos-1);		// 对两个子序列递归。
		QuickSort(A, pivotpos, high);
	}
}

int Partition(ElemType A[], int low, int high){	// 一趟划分
	ElemType pivot = A[low];		// 将当前表中第一个元素设为枢轴,对表进行划分
	while(low < high){ 				// 循环跳出条件
		while(low<high && A[high] >= pivot)	--high;	
		A[low] = A[high];			// 将比枢轴小的元素移动到左端
		while(low<high && A[low] <= pivot) ++low;
		A[high] = A[low];			// 将比枢轴大的元素移动到右端
	}
	A[low] = pivot;					// 枢轴元素放到最终位置
	return low;						// 返回枢轴元素的最终位置
}
选择排序

选一个最大(最小)放在前面,或后面。

归并排序

转载地址:https://www.cnblogs.com/lanhaicode/p/11284230.html

// 归并排序 将序列二分到1,然后递归合并
void MergeSort_UptoDowm(int* num, int start, int end){
    int mid = start +(end - start)/2;

    if(start >= end)        return ;
    
    MergeSort_UptoDowm(num, start, mid);    // 拆分
    MergeSort_UptoDowm(num, mid+1, end);    // 拆分

    merge(num, start, mid, end);            // 合并
}

void Merge(int *num, int start, int mid, int end){
    int *temp = (int *)malloc(sizof(int)*(end - start+1));
    // 申请空间来存放两个有序区归并后的临时区域
    int i = start;
    int j = mid+i;
    int k = 0;

    while(i <=mid && j<=end){		// 从小到大放入 堆区
        if(num[i] <=num[j]){
            temp[k++] = num[i++];
        }
        else{
            temp[k++] = num[j++]; 
        }   
    }
    while(i <= mid){	// 后面剩余的 放入堆区
        temp[k++] = num[i++];
    }
    while(j < =end){	
        temp[k++] = num[j++];
    }

    // 将临时区域中排序后的元素,整合到原数组中
    for(i = 0;i < k; i++)
    {
        num[start+i] = temp[i];
    }
    
    free(temp);	
}
基数排序
各种内部排序方法的比较讨论

红色

外部排序
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值