一、插入类排序.
二、交换类排序.
三、选择类排序.
四、归并类排序.
五、基数排序.
注:按关键字非递减排序(从小到大排序)。
交换类排序:通过“交换”无序序列中的记录从而得到其中关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。
1、冒泡排序
1.1、思想及代码实现
typedef int Elem;
void BubbleSort(Elem R[], int n){
int i = n;
while( i > 1 ){
int lastExchangeIndex = 1;
for(int j=1; j<i; ++j){
if(R[j+1] < R[j]){
Elem temp = R[j+1];
R[j+1] = R[j];
R[j] = temp;
lastExchangeIndex = j;
}//if
}//for
i = lastExchangeIndex;
}//while
}
冒泡排序的结束条件为:最后一趟没有进行“交换”。
1.2、时间性能分析
待整理
2、快速排序
2.1、思想及代码实现
一趟快速排序
目标:找一个记录,以它的关键字作为“枢轴”,凡其关键字小于枢轴关键字的记录均移动至枢轴记录之前;反之,凡关键字大于枢轴关键字的记录均移动至枢轴记录之后,保证一趟排序之后,记录的无序序列
R[s...t]
\textbf{R[s...t]}
R[s...t] 将分割成两部分:
R[s...(i-1)]
\textbf{R[s...(i-1)]}
R[s...(i-1)] 和
R[(i+1)...t]
\textbf{R[(i+1)...t]}
R[(i+1)...t] ,且
R[j].key
⩽
R[i].key
⩽
R[j].key
\qquad \qquad \textbf{R[j].key} \qquad \leqslant \qquad \textbf{R[i].key} \qquad \leqslant \qquad\textbf{R[j].key}
R[j].key⩽R[i].key⩽R[j].key
(
s
⩽
j
⩽
(
i
−
1
)
)
枢
轴
(
i
−
1
⩽
j
⩽
t
)
\qquad \qquad \big(s \leqslant j\leqslant (i-1) \big) \qquad \quad枢轴 \qquad \qquad \qquad \big(i-1 \leqslant j\leqslant t\big)
(s⩽j⩽(i−1))枢轴(i−1⩽j⩽t)
#define MAX_SIZE 20 //定义顺序表的最大长度
typedef int KeyType; //定义关键字类型为整数类型
typedef int InfoType;
typedef struct {
KeyType key; //关键字类型
InfoType info; //其他数据项类型
} RedType; //记录类型
typedef struct {
RedType r[MAX_SIZE+1]; //r[0]闲置或用作哨兵单元
int length; //顺序表长度
} SqList; //顺序表类型
// 方法1 //r[0] 存放数据
int Partition_No_Sentinel(SqList &L, int low, int high) {
//交换顺序表L中子表L.r[low .. high]的记录,枢轴记录到位,并返回其所在位置;
//此时在它之前(后)的记录均不大(小)于它。
KeyType pivotkey = L.r[low].key;//枢轴记录关键字
RedType temp;
while(low < high) {//从表的两端交替地向中间扫描
while(low < high && L.r[high].key >= pivotkey) {
--high;
}
temp = L.r[high];//将比枢轴记录小的记录移动到低端
L.r[high] = L.r[low];
L.r[low] = temp;
while(low < high && L.r[low].key <= pivotkey) {
++low;
}
temp = L.r[high];//将比枢轴记录大的记录移动到高端
L.r[high] = L.r[low];
L.r[low] = temp;
}
return low;//返回枢轴所在位置
}
// 方法2 //r[0] 不存放数据
int Partition(SqList &L, int low, int high) {
//交换顺序表L中子表L.r[low .. high]的记录,枢轴记录到位,并返回其所在位置;
//此时在它之前(后)的记录均不大(小)于它。
L.r[0] = L.r[low];//用子表的第一个记录做枢轴记录
KeyType pivotkey = L.r[low].key;//枢轴记录关键字
while(low < high) {//从表的两端交替地向中间扫描
while(low < high && L.r[high].key >= pivotkey) {
--high;
}// while
L.r[low] = L.r[high];//将比枢轴记录小的记录移动到低端
while(low < high && L.r[low].key <= pivotkey) {
++low;
}// while
L.r[high] = L.r[low];//将比枢轴记录大的记录移动到高端
}
L.r[low] = L.r[0];//枢轴记录 到位
return low;//返回枢轴位置
}//Partition
void QSort(SqList &L, int low, int high) {
//对顺序表L中的子序列L.r[low .. high]做快速排序
if(low < high) {//长度大于1
int pivotLoc = Partition(L, low, high);//将L.r[low .. high]一分为二
QSort(L, low, pivotLoc-1);//对低子表递归排序,pivotloc是枢轴位置
QSort(L, pivotLoc+1, high);//对高子表递归排序
}//if
}//QSort
void QuickSort(SqList &L){
QSort(L, 1, L.length);
}//QuickSort
2.2、时间性能分析
待整理
——《数据结构图 (C语言版) 严蔚敏》 学习笔记