基于线性表顺序存储结构,要求用插入和交换两种排序算法,对任一组数据按升序的顺序进行排序,体会这两种不同的算法设计。
关于待排序数据:要求元素个数不大于1000,数据可由键盘输入,样例如下:
输入样例:
5
1 6 9 2 5
输出样例:
1 2 5 6 9
交换排序:每次将数组中第 i 小的元素与第 i+1 到 n-1 小的元素比较。如果前者大于后者,则进行交换。在具体实现中,我们首先定义两个循环变量 i 和 j,分别代表待比较的元素下标,最外层的 i 循环从 0 开始遍历到 n-1,里面的 j 循环从 i+1 开始遍历到 n-1。在每一轮循环中,将下标为 i 和 j 的元素进行比较,若前者大于后者,则进行交换,否则不进行任何操作。
需要注意的是:为了防止数组越界,在 j 循环的终止条件中,我们将其改为 j < n,因为数组下标是从 0 开始计数的。代码如下图所示:
//交换排序
public static void exchangeSort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
if (a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
插入排序:在具体实现中,我们首先定义一个循环变量 i,从 1 开始遍历到 n-1,表示待插入的元素。将第 i 个元素保存在一个临时变量 temp 中,然后从 i-1 开始向前扫描,如果当前元素 a[j] 大于 temp,就将 a[j] 后移一位,将 j 指针向前移动一位,直到找到 a[j] <= temp 或者 j < 0,此时插入位置为 j + 1,把 temp 插入到 a[j+1] 的位置即可。代码如下所示:
//插入排序
public static void insertSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int temp = a[i];
int j = i - 1;
while (j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
}
整个代码如下所示:
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入待排列的个数:");
int n = sc.nextInt();
int a[] = new int[n];
System.out.println("请输入待排列的元素:");
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
System.out.println("进行插入排序:");
insertSort(a);
printArray(a);
System.out.println("进行交换排序:");
exchangeSort(a);
printArray(a);
}
//交换排序
public static void exchangeSort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
if (a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
//打印
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
//插入排序
public static void insertSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int temp = a[i];
int j = i - 1;
while (j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
}
}
基于线性表顺序存储结构的插入和交换两种排序算法结果图为
分别基于两种不同的存储结构(以线性表顺序存储结构、链式存储结构为例),要求用同一种排序算法(以插入算法为例)对任一组数据进行排序。
综合题1和题2,体会算法设计不依赖于数据存储结构,而算法实现依赖于数据存储结构。
关于待排序数据:要求元素个数不大于1000,数据可由键盘输入,样例如下:
输入样例:
5
1 6 9 2 5
输出样例:
1 2 5 6 9
首先创建链表节点类,代码如下所示:
/**
* 链表结点类
*/
static class Node {
int val;
Node next;
public Node() {
}
public Node(int val) {
this.val = val;
}
}
线性表顺序存储结构进行插入排序如第一题一致,代码如下所示:
//插入排序
public static void insertSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int temp = a[i];
int j = i - 1;
while (j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
}
链式存储结构进行插入排序:我们先创建一个带有头结点的链表(dummyHead),然后用 lastSorted 和 cur 两个 Node 类型的指针分别指向已经排好序的最后一个结点和待排序的第一个结点。从第二个结点开始,将 cur 指针向后移动,并依次将其插入到已排好序的链表中的合适位置。如果 cur 的值小于 lastSorted 的值,就需要从链表头开始往后查找插入位置,如果 cur 的值大于等于 lastSorted 的值,则将 lastSorted 向后移动一位,并将 cur 向后移动一位,直到 cur 指向链表尾部,排序完成。代码如下所示:
/**
* 使用链式存储结构进行插入排序
*/
public static Node insertSortWithLinkedList(Node head) {
if (head == null || head.next == null) {
return head;
}
Node dummyHead = new Node();
dummyHead.next = head;
Node lastSorted = head, cur = lastSorted.next;
while (cur != null) {
if (cur.val < lastSorted.val) {
Node prev = dummyHead;
while (prev.next.val < cur.val) {
prev = prev.next;
}
lastSorted.next = cur.next;
cur.next = prev.next;
prev.next = cur;
cur = lastSorted.next;
} else {
lastSorted = lastSorted.next;
cur = cur.next;
}
}
return dummyHead.next;
}
/**
* 打印链表
*/
public static void printLinkedList(Node head) {
while (head != null) {
System.out.print(head.val + " ");
head = head.next;
}
System.out.println();
}
整个代码如下所示:
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入待排列的个数:");
int n = sc.nextInt();
int a[] = new int[n];
System.out.println("请输入待排列的元素:");
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
System.out.println("进行插入排序:");
insertSort(a);
printArray(a);
// 使用链式存储结构进行排序
Node head = null, tail = null;
System.out.println("请输入待排序元素(链式结构):");
for (int i = 0; i < n; i++) {
int val = sc.nextInt();
Node newNode = new Node(val);
if (tail == null) {
head = tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
}
System.out.println("使用插入排序对链式结构进行排序:");
head = insertSortWithLinkedList(head);
printLinkedList(head);
}
//交换排序
public static void exchangeSort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
if (a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
//打印
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
//插入排序
public static void insertSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int temp = a[i];
int j = i - 1;
while (j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
}
/**
* 使用链式存储结构进行插入排序
*/
public static Node insertSortWithLinkedList(Node head) {
if (head == null || head.next == null) {
return head;
}
Node dummyHead = new Node();
dummyHead.next = head;
Node lastSorted = head, cur = lastSorted.next;
while (cur != null) {
if (cur.val < lastSorted.val) {
Node prev = dummyHead;
while (prev.next.val < cur.val) {
prev = prev.next;
}
lastSorted.next = cur.next;
cur.next = prev.next;
prev.next = cur;
cur = lastSorted.next;
} else {
lastSorted = lastSorted.next;
cur = cur.next;
}
}
return dummyHead.next;
}
/**
* 打印链表
*/
public static void printLinkedList(Node head) {
while (head != null) {
System.out.print(head.val + " ");
head = head.next;
}
System.out.println();
}
/**
* 链表结点类
*/
static class Node {
int val;
Node next;
public Node() {
}
public Node(int val) {
this.val = val;
}
}
}
基于两种不同的存储结构(以线性表顺序存储结构、链式存储结构为例)进行插入排序的结果图如下图所示: