8.3交换排序
2.编写双向冒泡算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行。
#include <iostream>
#include <algorithm>
using namespace std;
typedef int ElemType;
ElemType a[50];
void BubbleSort(ElemType a[], int n)
{
int low = 0, high = n - 1, i;
bool flag = true;
while (low < high && flag) {
flag = false;
for (i = low; i < high; i++) {
if (a[i] > a[i + 1]) {
swap(a[i], a[i + 1]);
flag = true;
}
}
high--;
for (i = high; i > low; i--) {
if (a[i] < a[i - 1]) {
swap(a[i], a[i - 1]);
flag = true;
}
}
low++;
}
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
BubbleSort(a, n);
for (int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}
3.已知线性表按顺序存储,且每个元素都是不相同的整形元素,设计把所有奇数移动到所有偶数前边的算法(要求时间最少,辅助空间最少)。
#include <iostream>
#include <algorithm>
using namespace std;
typedef int ElemType;
ElemType A[50];
void move(ElemType A[], int len)
{
int i = 0, j = len - 1;
while (i < j) {
while (i < j && A[i] % 2 != 0) i++;
while (i < j && A[j] % 2 != 1) j--;
if (i < j) {
swap(A[i], A[j]);
i++; j--;
}
}
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> A[i];
move(A, n);
for (int i = 0; i < n; i++) cout << A[i] << " ";
cout << endl;
return 0;
}
4.试重新编写考点精析中的快速排序的划分算法,使之美词选取的枢轴值都是随机地从当前子表中选择的。
#include <cstdlib>
#include <iostream>
using namespace std;
typedef int ElemType;
ElemType A[50];
int Partition2(ElemType A[], int low, int high)
{
int rand_Index = low + rand() % (high - low);
swap(A[rand_Index], A[low]);
ElemType pivot = A[low];
int i = low;
for (int j = low + 1; j <= high; j++)
if (A[j] < pivot) swap(A[++i], A[j]);
swap(A[i], A[low]);
return i;
}
void QuickSort(ElemType A[], int low, int high)
{
if (low < high) {
int pivotpos = Partition2(A, low, high);
QuickSort(A, low, pivotpos - 1);
QuickSort(A, pivotpos + 1, high);
}
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> A[i];
QuickSort(A, 1, n);
for (int i = 1; i <= n; i++) cout << A[i] << " ";
cout << endl;
return 0;
}
5.试编写一个算法,使之能够在数组L[1…n]中找出第k小的元素(即从小到大排序后处于第k个位置的元素)。
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int a[50];
int kth_elem(int a[], int low, int high, int k)
{
int rand_Index = low + rand() % (high - low + 1);
swap(a[rand_Index], a[low]);
int pivot = a[low];
int low_temp = low; int high_temp = high;
while (low < high) {
while (low < high && a[high] >= pivot) --high;
a[low] = a[high];
while (low < high && a[low] <= pivot) ++low;
a[high] = a[low];
}
a[low] = pivot;
if (low == k) return a[low];
else if (low > k) return kth_elem(a, low_temp, low - 1, k);
else return kth_elem(a, low + 1, high_temp, k);
}
int main()
{
int n, k;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
cin >> k;
int ans = kth_elem(a, 1, n, k);
cout << ans << endl;
return 0;
}
6.已知由 n ( n ≥ 2 ) n(n \geq 2) n(n≥2)个正整数构成的集合 A = a k ∣ 0 ≤ k < n A={a_{k}|0 \leq k < n} A=ak∣0≤k<n,将其划分为两个不相交的子集 A 1 A_{1} A1和 A 2 A_{2} A2,元素个数分别是 n 1 n_{1} n1和 n 2 n_{2} n2, A 1 A_{1} A1和 A 2 A_{2} A2中的元素之和分别为 S 1 S_{1} S1和 S 2 S_{2} S2。设计一个尽可能高效的划分算法,满足 ∣ n 1 − n 2 ∣ |n_{1}-n_{2}| ∣n1−n2∣最小且 ∣ S 1 − S 2 ∣ |S_{1}-S_{2}| ∣S1−S2∣最大。
#include <iostream>
using namespace std;
int a[50];
int setPartition(int a[], int n)
{
int pivotkey, low = 0, low0 = 0, high = n - 1, high0 = n - 1, flag = 1, k = n / 2, i;
int s1 = 0, s2 = 0;
while (flag) {
pivotkey = a[low];
while (low < high) {
while (low < high && a[high] >= pivotkey) --high;
if (low != high) a[low] = a[high];
while (low < high && a[low] <= pivotkey) ++low;
if (low != high) a[high] = a[low];
}
a[low] = pivotkey;
if (low == k - 1) flag = 0;
else {
if (low < k - 1) {
low0 = ++low;
high = high0;
} else {
high0 = --high;
low = low0;
}
}
}
for (i = 0; i < k; i++) s1 += a[i];
for (i = k; i < n; i++) s2 += a[i];
return s2 - s1;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int ans = setPartition(a, n);
cout << ans << endl;
return 0;
}
7.荷兰国旗问题:设有一个仅有红、白、蓝三种颜色的条块组成的条块序列,请编写一个时间复杂度为 Q ( n ) Q(n) Q(n)的算法,使得这些条块按红、白、蓝的顺序排好,即排成荷兰国旗图案。
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
char a[50];
void Flag_Arrange(char a[], int n)
{
int i = 0, j = 0, k = n - 1;
while (j <= k) {
switch (a[j]) {
case 'R': swap(a[i], a[j]); i++; j++; break;
case 'W': j++; break;
case 'B': swap(a[j], a[k]); k--;
}
}
}
int main()
{
cin >> a;
int n = strlen(a);
Flag_Arrange(a, n);
for (int i = 0; i < n; i++) cout << a[i];
return 0;
}
8.4选择排序
4.编写一个算法,在基于单链表表示的带排序关键字序列上进行简单选择排序。
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LinkNode {
ElemType data;
struct LinkNode *link;
} LinkNode, *LinkedList;
LinkedList init()
{
LinkedList head = (LinkedList)malloc(sizeof(LinkNode));
int n;
ElemType x;
scanf("%d", &n);
scanf("%d", &x);
head->data = x;
head->link = NULL;
LinkNode *tail = head;
for (int i = 1; i < n; i++) {
LinkedList temp = (LinkedList)malloc(sizeof(LinkNode));
scanf("%d", &x);
temp->data = x;
tail->link = temp;
temp->link = NULL;
tail = tail->link;
}
return head;
}
void selectSort(LinkedList &L)
{
LinkNode *h = L, *p, *q, *r, *s;
L = NULL;
while (h != NULL) {
p = s = h; q = r = NULL;
while (p != NULL) {
if (p->data > s->data) {
s = p;
r = q;
}
q = p;
p = p->link;
}
if (s == h) h = h->link;
else r->link = s->link;
s->link = L;
L = s;
}
}
void printList(LinkedList L)
{
while (L) {
printf("%d ", L->data);
L = L->link;
}
printf("\n");
}
int main()
{
LinkedList L = init();
selectSort(L);
printList(L);
return 0;
}
5.试设计一个算法,判断一个数据序列是够构成一个小根堆。
#include <iostream>
using namespace std;
typedef int ElemType;
ElemType A[50];
bool IsMinHeap(ElemType A[], int len)
{
if (len % 2 == 0) {
if (A[len / 2] > A[len]) return false;
for (int i = len / 2 - 1; i >= 1; i--)
if (A[i] > A[2 * i] || A[i] > A[2 * i + 1]) return false;
} else {
for (int i = len / 2; i >= 1; i--)
if (A[i] > A[2 * i] || A[i] > A[2 * i + 1]) return false;
}
return true;
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> A[i];
if (IsMinHeap(A, n)) cout << "Yes" << endl;
else cout << "No" << endl;
return 0;
}
8.6各种内部排序算法的比较与应用
4.设有一个数组中存放了一个无序的关键序列
K
1
,
K
2
,
…
,
K
n
K_{1},K_{2},…,K_{n}
K1,K2,…,Kn。现要求将
K
n
K_{n}
Kn放在将元素排序后的正确位置上,试编写实现该功能的算法,要求比较关键字的次数不超过
n
n
n。
#include <iostream>
using namespace std;
typedef int ElemType;
ElemType K[20];
int Partition(ElemType K[], int n)
{
int i = 1, j = n;
ElemType pivot = K[j];
while (i < j) {
while (i < j && K[i] <= pivot) i++;
if (i < j) K[j] = K[i];
while (i < j && K[j] >= pivot) j--;
if (i < j) K[i] = K[j];
}
K[i] = pivot;
return i;
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> K[i];
int p = Partition(K, n);
cout << p << endl;
return 0;
}