数据结构--Chapter7(内排序)

7. 内排序

7.1 排序的基本概念

1. 排序的定义

    所谓排序,简单地说就是将一组“无序”的记录序列调整为“有序”的举例序列的一种操作。通常待排序的记录有多个数据项,把用于作为排序依据的数据项称为关键字。例如,学生成绩表由学号、姓名和各科成绩等数据项组成,这些数据项都可作为关键字来进行排序。

2. 排序的分类

1)内部排序和外部排序

    按照排序过程中所涉及的存储器的不同可分为内部排序与外部排序。内部排序是指待排序序列完全存放在内存中进行的排序过程,这种方法适合数量不太大的数据元素的排序。外部排序是指待排序的数据元素非常多,以至于它们必须存储在外部存储器上,这种排序过程中需要访问外存储器,这样的排序称为外排序。

2)稳定排序与不稳定排序

    若对任意一组数据元素序列,使用某种排序算法对它进行按照关键字的排序,若相同关键字间的前后位置关系在排序前与排序后保持一致,则称此排序方法是稳定的,而不能保持一致的排序方法则称为不稳定的。例如,一组关键字序列{3,4,2,3,1},若经过排序后变为{1,2,3,3,4},则此排序方法是稳定的;若经过排序后变为{1,2,3,3,4},则此排序方法是不稳定的。

3. 内排序的方法

    内部排序的过程是一个逐步扩大记录的优先序列长度的过程。基于不同的“扩大”有序序列长度的方法,内部排序方法大致可分为以下几种类型:插入类、交换类、选择类、归并类和其他类。

1)插入类排序方法是指将无序子序列中的一个或几个记录“插入”到有序序列中,从而增加记录的有序子序列的长度。

2)交换类排序方法是指通过“交换”无序序列中的记录,从而得到其中关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。

3)选择类排序方法是指从记录的无序子序列中“选择”关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。

4)归并类排序方法是指通过“归并”两个或两个以上的记录有序子序列,逐步增加记录有序序列的长度。

4. 排序算法的性能评价

    排序算法有很多种,在众多的排序算法中,简单地评价哪一种算法是好的很困难。通常认为某种算法是用于某些情况,而这种算法在另外情况下性能也就不如其他算法。评价排序算法好换的标准主要有两条:算法的时间复杂度和空间复杂度。

5. 待排序记录的类描述

    内部排序方法可在不同的存储结构上实现,但待排序的数据元素集合通常以线性表为主,因此存储结构多选用顺序表和链表。此外,顺序表又具有随机存取的特性,因此这儿介绍的排序算法都是针对顺序表进行操作的。

    待排序的顺序表记录类描述如下:


package chapter7;

public class RecordNode {
	public KeyType key;// 关键字
	public ElementType element;// 数据类型

	public RecordNode(KeyType key) {
		this.key = key;
	}

	public RecordNode(KeyType key, ElementType element) {
		this.key = key;
		this.element = element;
	}
}

    顺序表记录关键字类

package chapter7;

/**
 * 顺序表记录关键字类
 * 
 * @author Oner.wv
 *
 */
public class KeyType implements Comparable<KeyType> {

	public int key;// 关键字

	public KeyType() {
	}

	public KeyType(int key) {
		this.key = key;
	}

	@Override
	public String toString() {// 覆盖toString方法
		return key + " ";
	}

	@Override
	public int compareTo(KeyType another) {// 覆盖Comparable接口中比较关键字大小的方法
		int thisVal = this.key;
		int anotherVal = another.key;
		return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
	}
}


    顺序表记录节点类

package chapter7;

/**
 * 顺序表记录节点类
 * 
 * @author Oner.wv
 *
 */
public class ElementType {
	public String data;// 用户可自定义其他数据类型

	public ElementType() {
	}

	public ElementType(String data) {
		this.data = data;
	}

	public String toString() {
		return data;
	}

}


    待排序的顺序表类描述如下:

package chapter7;

public class SeqList {
	public RecordNode[] r;// 顺序表记录节点数组
	public int curlen;// 顺序表长度

	// 顺序表的构造方法,构造一个存储空间为maxSize个存储单元
	public SeqList(int maxSize) {
		this.r = new RecordNode[maxSize];// 为顺序表分配maxSize个存储单元
		int curlen = 0;// 置顺序表的当前长度为0
	}

	// 在当前顺序表的第i个结点之前插入一个RecordNode类型的节点x
	public void insert(int i, RecordNode x) throws Exception {
		if (curlen == r.length) {// 判断顺序表是否已满
			throw new Exception("顺序表已满");
		}
		if (i < 0 || i > curlen) {
			throw new Exception("插入位置不合理");
		}
		for (int j = curlen; j > i; j--) {
			r[i] = r[i - 1];// 插入位置及以后的数据元素后移
		}
		r[i] = x;// 插入x
		this.curlen++;// 表长度加1
	}
}


7.2 插入排序

    这儿介绍两种插入排序方法:直接插入排序和希尔排序

7.2.1 直接插入排序

    直接插入排序(Straight Insertion Sort)是一种简单地排序方法,其基本思想先将原序列分为有序区和无序区,然后再经过比较和后移操作将无序区元素插入到有序区中

    看下面的一个例子:    
           下标: 0    1   2    3    4

初始关键字:[52] 39 67  70  52

            i=1:[39  52] 67  70 52

            i=2:[39  52  67] 70 52

            i=3:[39  52  67 70] 52

            i=4:[39  52 52 67 70]

    直接插入排序算法的主要步骤归纳如下:

1)将r[i]暂存在临时变量temp中。

2)将temp与r[j](j=i-1,i-2,...,0)依次比较,若temp.key<r[j].key,则将r[j]后移一个位置,知道temp.key>=r[j].key为止(此时j+1即为r[i]插入位置)。

3)将temp插入到第j+1个位置上。

4)令i=1,2,3,...,n

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值