关键字 是数据元素中的某个数据项。如果某个数据项可以唯一地确定一个数据元素,就将其称为主关键字;否则,称为次关键字。
排序 是把一组无序地数据元素按照关键字值递增(或递减)地重新排列。如果排序依据的是主关键字,排序的结果将是唯一的,
排序算法的稳定性 如果在待排序的记录序列中有多个数据元素的关键字值相同,经过排序后,这些数据元素的相对次序保持不变,则称这种排序算法是稳定的,否则称之为不稳定的。
1.======================================插入排序=============================================
直接插入排序是一种比较简单的排序方法。它的基本思想是依次将记录序列中的每一个记录插入到有序段中,使有序段的长度不断地扩大。其具体的排序过程可以描述如下:首先将待排序记录序列中的第一个记录作为一个有序段,将记录序列中的第二个记录插入到上述有序段中形成由两个记录组成的有序段,再将记录序列中的第三个记录插入到这个有序段中,形成由三个记录组成的有序段,…依此类推,每一趟都是将一个记录插入到前面的有序段中,假设当前欲处理第i个记录,则应该将这个记录插入到由前i-1个记录组成的有序段中,从而形成一个由i个记录组成的按关键字值排列的有序序列,直到所有记录都插入到有序段中。一共需要经过n-1趟就可以将初始序列的n个记录重新排列成按关键字值大小排列的有序序列。
直接插入排序算法:
将第i个记录插入到由前面i-1个记录构成的有序段中主要有4个步骤:
⑴ 将待插入记录R[i] 保存在R[0]中,即R[0]=R[i];
⑵ 搜索插入位置: 在 R[1..i-1] 中查找 R[i] 的插入位置,即确定j(0≤j<i)使得R[1..j].key≤R[i].key<R[j+1..i-1].key
(3)将 R[j+1..i-1] 中的记录后移一个位置; (4) 将 R[i] 插入到 j+1 的位置。
和讨论的顺序查找类似,为了避免在查找过程中判别循环变量是否出界,设置 R[0] 为监视哨,并在查找的同时进行“记录后移” 。
源码:
排序序列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define MAXSIZE 100 #define OVERFLOW_ERROR -1 typedef int KeyType; typedef int Status; typedef int OtherInfo; typedef struct { KeyType key;//关键字 OtherInfo info;//其他相关的信息 } RedType;//关键字的相关信息 //线性表的相关信息 typedef struct { RedType *elem;//元素 int length;//元素长度 } Straight_Sort; int number;//数组的具体长度 int flag_maker = 0;//次数转变的变量 int maker = 0;//标识排序的具体次数 //打印好已经排序好的序列和刚开始初始化时的序列 Status print_Sort(Straight_Sort straight_array) { int i = 0; for(i = 1; i<=number; i++ ) { printf(" %d", straight_array.elem[i].key); } printf("n"); return TRUE; } Status print_Straight_Sort(Straight_Sort straight_array) { int i = 0; for(i = 1; i<=number; i++ ) { printf(" %d", straight_array.elem[i].key); } flag_maker = flag_maker + 1; printf("t排序次数 %d", maker); printf("n"); if( flag_maker == straight_array.length) { maker = 0; } return TRUE; } //直接初始化和赋值 Status Init_Straight_Sort(Straight_Sort &straight_array) { int elem; //分配长度 straight_array.elem = new RedType[MAXSIZE]; //存储元素数据应该从数组的第一位开始存储 straight_array.length = 0; //文件操作 FILE *pFile; //返回的是文件的地址 pFile = fopen("liuwenhao.txt","r"); //文件打开失败 if(pFile == NULL) { printf("cannot open file liuwenhao.txt"); return FALSE; exit(OVERFLOW_ERROR); } //从文件里面取值,是一个一个的取值 fscanf(pFile,"%d",&number); for(int i = 0; i<=number; i++) { straight_array.elem[i].key = NULL;//地址初始化为NULL } for(int i = 1; i<=number; i++) { //获取关键字 fscanf(pFile,"%d",&elem); straight_array.elem[straight_array.length+1].key = elem; straight_array.length = straight_array.length + 1; } return TRUE; } //直接插入算法 Status straight_Insert_Sort(Straight_Sort &straight_array) { int j; for(int i = 2; i <= straight_array.length; i++) { if(straight_array.elem[i].key < straight_array.elem[i-1].key) { //将待插的数据放在监视哨位置 straight_array.elem[0].key = straight_array.elem[i].key; //数组位置后移 straight_array.elem[i].key = straight_array.elem[i-1].key; //移动过程 maker = maker + 1; //找到带插入位置 for(j = i-2; straight_array.elem[0].key < straight_array.elem[j].key; j--) { //没找到合适的位置数据后移 straight_array.elem[j+1].key = straight_array.elem[j].key; //找插入位置的过程中 maker = maker + 1; } //找到执行 straight_array.elem[j+1].key = straight_array.elem[0].key; //找到交换位置的过程 maker = maker + 1; } //打印 print_Straight_Sort(straight_array); } return TRUE; } //主函数 int main(void) { Straight_Sort straight_array; Init_Straight_Sort(straight_array); printf("t输出排序前序列...n"); print_Sort(straight_array); printf("n"); printf("t输出排序过程中的序列...n"); straight_Insert_Sort(straight_array); printf("t输出排序后序列...n"); print_Sort(straight_array); printf("n"); return 0; }
结果:
直接插入排序算法简单、容易实现,只需要一个记录大小的辅助空间用于存放待插入的记录(在C语言中,我们利用了数组中的0单元)和两个int型变量。当待排序记录较少时,排序速度较快,但是,当待排序的记录数量较大时,大量的比较和移动操作将使直接插入排序算法的效率降低;然而,当待排序的数据元素基本有序时,直接插入排序过程中的移动次数大大减少,从而效率会有所提高。 直接插入排序是一种稳定的排序方法。
直接插入排序的时间复杂度 从上述排序过程可见,排序中的两个基本操作是:(关键字间的)比较和(记录的)移动。因此排序的时间性能取决于排序过程中这两个操作的次数。从直接插入排序的算法可见,这两个操作的次数取决于待排记录序列的状态,当待排记录处于“正序”(即记录按关键字从小到大的顺序排列)的情况时,所需进行的关键字比较和记录移动的次数最少,反之,当待排记录处于“逆序”(即记录按关键字从大到小的顺序排列)的情况时,所需进行的关键字比较和记录移动的次数最多。
2.==========================================折半插入排序==========================================
由于插入排序的基本思想是在一个有序序列中插入一个新的记录,则可以利用“折半查找”查询插入位置,由此得到的插入排序算法为“折半插入排序”
源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define MAXSIZE 100 #define OVERFLOW_ERROR -1 typedef int KeyType; typedef int Status; typedef int OtherInfo; typedef struct { KeyType key;//关键字 OtherInfo info;//其他相关的信息 } RedType;//关键字的相关信息 //线性表的相关信息 typedef struct { RedType *elem;//元素 int length;//元素长度 } Binary_Sort; int number;//数组的具体长度 int flag_maker = 0;//次数转变的变量 int maker = 0;//标识排序的具体次数 //打印好已经排序好的序列和刚开始初始化时的序列 Status print_Sort(Binary_Sort binary_array) { int i = 0; for(i = 1; i<=number; i++ ) { printf(" %d", binary_array.elem[i].key); } printf("n"); return TRUE; } Status print_Binary_Sort(Binary_Sort binary_array) { int i = 0; for(i = 1; i<=number; i++ ) { printf(" %d", binary_array.elem[i].key); } flag_maker = flag_maker + 1; printf("t排序次数 %d", maker); printf("n"); if( flag_maker == binary_array.length) { maker = 0; } return TRUE; } //直接初始化和赋值 Status Init_Binary_Sort(Binary_Sort &binary_array) { int elem; //分配长度 binary_array.elem = new RedType[MAXSIZE]; //存储元素数据应该从数组的第一位开始存储 binary_array.length = 0; //文件操作 FILE *pFile; //返回的是文件的地址 pFile = fopen("liuwenhao.txt","r"); //文件打开失败 if(pFile == NULL) { printf("cannot open file liuwenhao.txt"); return FALSE; exit(OVERFLOW_ERROR); } //从文件里面取值,是一个一个的取值 fscanf(pFile,"%d",&number); for(int i = 0; i<=number; i++) { binary_array.elem[i].key = NULL;//地址初始化为NULL } for(int i = 1; i<=number; i++) { //获取关键字 fscanf(pFile,"%d",&elem); binary_array.elem[binary_array.length+1].key = elem; binary_array.length = binary_array.length + 1; } return TRUE; } //直接插入算法 Status binary_Insert_Sort(Binary_Sort &binary_array) { int j; for(int i = 2; i <= binary_array.length; i++) { if(binary_array.elem[i].key < binary_array.elem[i-1].key) { //将待插的数据放在监视哨位置 binary_array.elem[0].key = binary_array.elem[i].key; //数组位置后移 binary_array.elem[i].key = binary_array.elem[i-1].key; //移动过程 maker = maker + 1; //找到带插入位置 for(j = i-2; binary_array.elem[0].key < binary_array.elem[j].key; j--) { //没找到合适的位置数据后移 binary_array.elem[j+1].key = binary_array.elem[j].key; //找插入位置的过程中 maker = maker + 1; } //找到执行 binary_array.elem[j+1].key = binary_array.elem[0].key; //找到交换位置的过程 maker = maker + 1; } //打印 print_Binary_Sort(binary_array); } return TRUE; } //主函数 int main(void) { Binary_Sort binary_array; Init_Binary_Sort(binary_array); printf("t输出排序前序列...n"); print_Sort(binary_array); printf("n"); printf("t输出排序过程中的序列...n"); binary_Insert_Sort(binary_array); printf("t输出排序后序列...n"); print_Sort(binary_array); printf("n"); return 0; }
结果:
最后
以上就是深情便当最近收集整理的关于数据结构===》排序之直接插入和折半插入的全部内容,更多相关数据结构===》排序之直接插入和折半插入内容请搜索靠谱客的其他文章。
发表评论 取消回复