这几日整理出了大一时学习的数据结构中排序算法中的部分内容,写了一个简单的排序算法的程序。想写出来分享一下,也算是自己的学习日记。
程序功能是: 输入一个待排序记录序列,选择一种算法,然后输出一个有序的序列。
一、运行过程及截图如下:
1、输入一个有序序列长度,回车,输入各个记录的关键字,如下图
2、回车,打印出算法选择列表,选择你要选择的算法(比如选1、直接插入排序)
3、回车,得到输出结果
二、代码实现过程(VS 2013)
1、新建一个win 32控制台应用程序,分别为插入排序、交换排序、选择排序和归并排序各建立一个文件,如下图:
2、代码编写
2.1插入排序
2.1.1直接插入排序算法实现
- //直接插入排序
- void DirectInsertSort(Record r[], int length)
- //参数Record[]为排序的数据元素序列,length表示序列长度
- {
- <span style="white-space:pre"> </span>r[0] = r[i]; //r[0]用作监视哨,将带插入的记录放进去
- int i, j;
- for (i = 2; i <= length; i++)
- {
- <span style="white-space:pre"> </span>r[j + 1] = r[j];
- j = i - 1;
- while (r[0].key < r[j].key)
- {
- j--;
- }
- }
- r[j + 1] = r[0];
- }
- <span style="white-space:pre"> </span>//二分插入排序
- <span style="white-space:pre"> </span>void BinaryInsertSort(Record r[], int length)
- <span style="white-space:pre"> </span>//r[]为排序的数据元素序列,length表示序列长度
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int i, j;
- <span style="white-space:pre"> </span>int mid, high;
- <span style="white-space:pre"> </span>int low;
- <span style="white-space:pre"> </span>for (i = 2; i <= length; i++)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>r[0] = r[i]; //r[0]用作监视哨,将带插入的记录放进去
- <span style="white-space:pre"> </span>low = 1;
- <span style="white-space:pre"> </span>high = i - 1;
- <span style="white-space:pre"> </span>while (low <= high) //while循环找出要插入的位置
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>mid = (low + high) / 2;
- <span style="white-space:pre"> </span>if (r[i].key < r[mid].key)
- <span style="white-space:pre"> </span> high = mid - 1;
- <span style="white-space:pre"> </span>else low = mid + 1;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>for (j = i - 1; j >= low; --j)
- <span style="white-space:pre"> </span>r[j + 1] = r[j]; //记录向后移动
- <span style="white-space:pre"> </span>r[low] = r[0]; //插入记录
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>//单趟希尔排序
- <span style="white-space:pre"> </span>void SingleShellInsert_Sort(Record r[], int length, int d)
- <span style="white-space:pre"> </span>//r[]为排序的数据元素序列,length表示序列长度,d表示第一次的增量
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> int i, j;
- <span style="white-space:pre"> </span>for (i = 1 + d; i <= length; i++)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> if (r[i].key < r[i - d].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r[0] = r[i]; //备份r[i],不做监视哨
- <span style="white-space:pre"> </span> j = i - d;
- <span style="white-space:pre"> </span> while (j>0 && r[0].key < r[j].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r[j + d] = r[j];
- <span style="white-space:pre"> </span> j = j - d;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> r[j + d] = r[0];
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>//希尔排序
- <span style="white-space:pre"> </span>void ShellInsertSort(Record r[], int length, int d[], int n)
- <span style="white-space:pre"> </span>/*r[]为排序的数据元素序列,length表示数组r的长度,d[]是增量数组,n是数组d的长度*/
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> int i;
- <span style="white-space:pre"> </span> for (i = 0; i < n; i++)
- <span style="white-space:pre"> </span> Single_ShellInsertSort(r, length, d[i]);
- <span style="white-space:pre"> </span>}
2.2.1冒泡排序算法实现
- <span style="white-space:pre"> </span>//冒泡排序
- <span style="white-space:pre"> </span>void BubbleSort(Record r[], int length)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int mark; //标志,当没有交换操作时为0,有交换操作时为1
- <span style="white-space:pre"> </span>int i, j; //计数变量
- <span style="white-space:pre"> </span>for (i = 1; i <= length; i++)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> mark = 0;
- <span style="white-space:pre"> </span> for (j = i+1; j <= length; j++)
- <span style="white-space:pre"> </span> { //两两相邻进行比较,若逆序,则交换位置
- <span style="white-space:pre"> </span> if (r[i].key > r[i + 1].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r[0] = r[i];
- <span style="white-space:pre"> </span> r[i] = r[i - 1];
- <span style="white-space:pre"> </span> r[i - 1] = r[i];
- <span style="white-space:pre"> </span> mark = 1;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> if (mark == 0) break;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>//单趟快速排序,返回枢轴元素的位置
- <span style="white-space:pre"> </span>int SingleQuickSort(Record r[], int low, int high)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>//low是待排序列的下边界,high是待排序列的上边界
- <span style="white-space:pre"> </span>Record temp;
- <span style="white-space:pre"> </span>int i, j;
- <span style="white-space:pre"> </span>i = low;
- <span style="white-space:pre"> </span>j = high;
- <span style="white-space:pre"> </span>temp = r[low];
- <span style="white-space:pre"> </span>while (i < j)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> while (r[j].key >= temp.key)<span style="white-space:pre"> </span>//high 从右到左找小于temp.key的记录
- <span style="white-space:pre"> </span> j--;
- <span style="white-space:pre"> </span>if (i < j)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>r[i] = r[j];
- <span style="white-space:pre"> </span>i++;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>while (i < j&&r[i].key < temp.key)<span style="white-space:pre"> </span>//low从左到右找大于temp.key的记录
- <span style="white-space:pre"> </span>i++;
- <span style="white-space:pre"> </span>if (i < j)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> r[j] = r[i];
- <span style="white-space:pre"> </span>j--;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>r[i] = temp; //退出循环时必有i=j
- <span style="white-space:pre"> </span>return i;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>//快速排序
- <span style="white-space:pre"> </span>void QuickSort(Record r[], int low, int high)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int pos;
- <span style="white-space:pre"> </span>if (low < high)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> pos = SingleQuickSort(r, low, high);
- <span style="white-space:pre"> </span> Quick_Sort(r, low, pos - 1);
- <span style="white-space:pre"> </span> Quick_Sort(r, pos + 1, high);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
2.3.1简单选择排序算法实现
- <span style="white-space:pre"> </span>//简单选择排序
- <span style="white-space:pre"> </span>void SimpleSelectSort(Record r[], int length)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int i, j; //计数变量
- <span style="white-space:pre"> </span>int k; //记录没趟选择最小值的位置
- <span style="white-space:pre"> </span>Record temp;
- <span style="white-space:pre"> </span>for (i = 1; i < length; i++)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> r[0] = r[i];
- <span style="white-space:pre"> </span>k = i;
- <span style="white-space:pre"> </span>for (j = i + 1; j <= length; j++)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> if (r[j].key < r[0].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r[0] = r[j];
- <span style="white-space:pre"> </span> k = j;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>if (k != i)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> temp = r[k];
- <span style="white-space:pre"> </span> r[k] = r[i];
- <span style="white-space:pre"> </span> r[i] = temp;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>/* 堆排序,小顶堆 */
- <span style="white-space:pre"> </span>/* 完全二叉树的性质,左右子节点的关系明确,,i节点的左孩子节点为2*i,右孩子节点为2*i+1
- <span style="white-space:pre"> </span>顺序存储的待排序列数组本身就可以反映节点之间的关系,就是一棵二叉树*/
- <span style="white-space:pre"> </span>// 将二叉树调整为小顶堆
- <span style="white-space:pre"> </span>void Adjust2Heap(Record r[], int length)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int i, j;
- <span style="white-space:pre"> </span>int n = length; //序列长度的副本,不改变length的值
- <span style="white-space:pre"> </span>Record temp;
- <span style="white-space:pre"> </span>int ID;
- <span style="white-space:pre"> </span>for (i = n / 2; i >= 1; i--)
- <span style="white-space:pre"> </span>{ //找出非叶子节点和它的孩子中最小的,与非叶子节点交换
- <span style="white-space:pre"> </span> /*易错点:此处要考虑n是奇数还是偶数,若是奇数,则最后一个非叶子节点有两个孩子;
- <span style="white-space:pre"> </span> 若是偶数,只有一个左孩子,没有右孩子。两种情况要分开讨论,否则n为偶数时排序出错*/
- <span style="white-space:pre"> </span>ID = i;
- <span style="white-space:pre"> </span>temp = r[i];
- <span style="white-space:pre"> </span>if (i != n / 2 || n % 2 == 1)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> if (r[i * 2].key < r[i * 2 + 1].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> if (r[i * 2].key < r[i].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r[i] = r[i * 2];
- <span style="white-space:pre"> </span> r[i * 2] = temp;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span> else if (r[i * 2 + 1].key < r[i].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r[i] = r[i * 2 + 1];
- <span style="white-space:pre"> </span> r[i * 2 + 1] = temp;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>else{
- <span style="white-space:pre"> </span> if (r[i * 2].key < r[i].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r[i] = r[i * 2];
- <span style="white-space:pre"> </span> r[i * 2] = temp;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>//堆排序
- <span style="white-space:pre"> </span>void HeapTreeSort(Record r[], int length)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int i, j = 1; //计数变量
- <span style="white-space:pre"> </span>int n = length; //length的副本,过程中不改变length的值
- <span style="white-space:pre"> </span>Record r2[MAXSIZE]; //r[]的副本,过程中不改变r[]的值
- <span style="white-space:pre"> </span>for (i = 1; i <= length; i++)
- <span style="white-space:pre"> </span> r2[i] = r[i];
- <span style="white-space:pre"> </span>for (n; n > 1; n--)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> Adjust2Heap(r2, n);
- <span style="white-space:pre"> </span> r[j] = r2[1];
- <span style="white-space:pre"> </span> r2[1] = r2[n];
- <span style="white-space:pre"> </span> j++;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>r[j] = r2[n+1];
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>/* 一次二路归并 */
- <span style="white-space:pre"> </span>void SingleMergingSort(Record r1[], int low, int mid, int high, Record r2[])
- <span style="white-space:pre"> </span>//将有序数组r1[]={ r1[low],r[low+1],...,r[mid] } 和有序数组 r1[]={ r1[mid+1],r1[mid+2],...,r1[high] }
- <span style="white-space:pre"> </span>//合并成一个有序序列,存放在r2[low,......,high]中
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int i = low; //r1[]前部分的指示变量
- <span style="white-space:pre"> </span>int j = mid + 1; //r1[]后部分的指示变量
- <span style="white-space:pre"> </span>int k = low; //r2[]的位置指示变量
- <span style="white-space:pre"> </span>while (i <= mid&&j <= high)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> if (r1[i].key < r1[j].key)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> r2[k] = r1[i];
- <span style="white-space:pre"> </span> i++;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> else{
- <span style="white-space:pre"> </span> r2[k] = r1[j];
- <span style="white-space:pre"> </span> j++;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> k++;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>while (i <= mid&&j > high)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> r2[k] = r1[i];
- <span style="white-space:pre"> </span> k++;
- <span style="white-space:pre"> </span> i++;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>while (i > mid&&j <= high)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> r2[k] = r1[j];
- <span style="white-space:pre"> </span> k++;
- <span style="white-space:pre"> </span> j++;
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>void MSort(Record r1[], int low, int high, Record r3[])
- <span style="white-space:pre"> </span>//将数组r1[]排序后,存储到r3[]中,递归思想
- <span style="white-space:pre"> </span>/* 要将r1[low...mid]和r1[mid+1,...high]归并排序,
- <span style="white-space:pre"> </span> 得先将r[low,mid]内部分为两个子序列,调用二路归并排序
- <span style="white-space:pre"> </span> 再分别对两个子序列执行同样操作;
- <span style="white-space:pre"> </span> 再将r[mid+1....high]内部分为两个子序列,
- <span style="white-space:pre"> </span>同样处理,最终可得到排序结果*/
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int mid;
- <span style="white-space:pre"> </span>Record r2[MAXSIZE]; //辅助空间
- <span style="white-space:pre"> </span>if (low == high)
- <span style="white-space:pre"> </span> r3[low] = r1[low];
- <span style="white-space:pre"> </span>else{
- <span style="white-space:pre"> </span> mid = (low + high) / 2;
- <span style="white-space:pre"> </span> MSort(r1, low, mid, r2);
- <span style="white-space:pre"> </span> MSort(r1, mid + 1, high, r2);
- <span style="white-space:pre"> </span> SingleMergingSort(r2, low, mid, high, r3);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>void MergingSort(Record r[], int length)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>MSort(r, 1, length, r);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>#include "stdafx.h"
- <span style="white-space:pre"> </span>#include "InsertSort.h"
- <span style="white-space:pre"> </span>#include "ExchangeSort.h"
- <span style="white-space:pre"> </span>#include "SelectSort.h"
- <span style="white-space:pre"> </span>#include "MergingSort.h"
- <span style="white-space:pre"> </span>int _tmain(int argc, _TCHAR* argv[])
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>int len, d_len; //排序记录长度、增量数组长度
- <span style="white-space:pre"> </span>int i; //计数变量
- <span style="white-space:pre"> </span>int choice = 1; //选择变量
- <span style="white-space:pre"> </span>int low, high; //快速排序的指示边界的变量
- <span style="white-space:pre"> </span>Record r[MAXSIZE];
- <span style="white-space:pre"> </span>int d[MAXSIZE];
- <span style="white-space:pre"> </span>low = 1;
- <span style="white-space:pre"> </span>printf("请输入带排序记录长度:\n");
- <span style="white-space:pre"> </span>scanf_s("%d", &len);
- <span style="white-space:pre"> </span>high = len;
- <span style="white-space:pre"> </span>printf("请依次输入各个记录的关键字(空格隔开):\n");
- <span style="white-space:pre"> </span>for (i = 1; i <= len; i++)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span> scanf_s("%d", &r[i].key);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>system("CLS");
- <span style="white-space:pre"> </span>//输出选择排序算法菜单
- <span style="white-space:pre"> </span> while (choice != 0)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span> printf("*------------------------------------------------*\n");
- <span style="white-space:pre"> </span> printf("*\t请选择排序方法:\n");
- <span style="white-space:pre"> </span> printf("*\t1、直接插入排序\t2、二分插入排序\t3、希尔排序\n");
- <span style="white-space:pre"> </span> printf("*\t4、冒泡排序\t5、快速排序\t6、简单选择排序\n");
- <span style="white-space:pre"> </span> printf("*\t7、堆排序\t8、归并排序\t0、退出\n");
- <span style="white-space:pre"> </span> printf("*------------------------------------------------*\n");
- <span style="white-space:pre"> </span> printf("*\t请输入你的选择:\t");
- <span style="white-space:pre"> </span> scanf_s("%d", &choice);
- <span style="white-space:pre"> </span> system("cls");
- <span style="white-space:pre"> </span> switch (choice)
- <span style="white-space:pre"> </span> {
- <span style="white-space:pre"> </span> case 0:
- <span style="white-space:pre"> </span> exit(0);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 1:
- <span style="white-space:pre"> </span> DirectInsertSort(r, len);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 2:
- <span style="white-space:pre"> </span> BinaryInsertSort(r, len);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 3:
- <span style="white-space:pre"> </span> printf("请输入增量数组的长度:\n");
- <span style="white-space:pre"> </span> scanf_s("%d", &d_len);
- <span style="white-space:pre"> </span> printf("请输入增量数组的各元素(空格隔开):\n");
- <span style="white-space:pre"> </span> for (i = 0; i < d_len; i++)
- <span style="white-space:pre"> </span> scanf_s("%d", &d[i]);
- <span style="white-space:pre"> </span> ShellInsertSort(r, len, d, d_len);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 4:
- <span style="white-space:pre"> </span> BubbleSort(r, len);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 5:
- <span style="white-space:pre"> </span> QuickSort(r, low, high);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 6:
- <span style="white-space:pre"> </span> SimpleSelectSort(r, len);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 7:
- <span style="white-space:pre"> </span> HeapTreeSort(r, len);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> case 8:
- <span style="white-space:pre"> </span> MergingSort(r, len);
- <span style="white-space:pre"> </span> break;
- <span style="white-space:pre"> </span> default:
- <span style="white-space:pre"> </span> printf("输入选择有误!");
- <span style="white-space:pre"> </span> getchar();
- <span style="white-space:pre"> </span> getchar();
- <span style="white-space:pre"> </span><span style="white-space:pre"> </span> exit(0);
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> printf("排序结果如下:\n");
- <span style="white-space:pre"> </span>for (i = 1; i <= len; i++)
- <span style="white-space:pre"> </span> printf(" %d", r[i].key);
- <span style="white-space:pre"> </span>getchar();
- <span style="white-space:pre"> </span>getchar();
- <span style="white-space:pre"> </span>system("cls");
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>getchar();
- <span style="white-space:pre"> </span>getchar();
- <span style="white-space:pre"> </span>return 0;
- <span style="white-space:pre"> </span>}