排序章节完结

完结撒花~
This commit is contained in:
Ruvikm
2021-03-16 09:23:01 +08:00
parent 5659116749
commit efdfe80778
11 changed files with 847 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define ElemType int
#define _for(i,a,b) for(int i=(a);i<(b);i++)
//P323.2
//编写双向冒泡排序算法, 在正反两个方向交替进行扫描, 即第一趟把关键字最大的元素
//放在序列的最后面, 第二趟把关键字最小的元素放在序列的最前面, 如此反复进行。
void BubbleSort(vector<ElemType> &A) {
int low = 0, high = A.size() - 1;
bool flag = true;
while (low < high && flag) {
flag = false;
_for(i, low, high) {
if (A[i] > A[i + 1]) {
swap(A[i], A[i + 1]);
flag = true;
}
}
high--;
for (int i = high; i > low; i--) {
if (A[i] < A[i - 1]) {
swap(A[i], A[i - 1]);
flag = true;
}
}
low++;
}
}
void Print(vector<ElemType> A) {
_for(i, 0, A.size()) {
cout << A[i] << " ";
}
cout << endl;
}
int main()
{
vector<ElemType> A{ 2,5,21,54,64,12,65,34,12,37,21 };
cout << "排序前:" << endl;
Print(A);
BubbleSort(A);
cout << "排序后:" << endl;
Print(A);
return 0;
}

View File

@@ -0,0 +1,91 @@
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#pragma region 建立顺序存储的线性表
#define MAX 30
#define _for(i,a,b) for( int i=(a); i<(b); ++i)
#define _rep(i,a,b) for( int i=(a); i<=(b); ++i)
typedef struct {
int data[MAX];
int length;
}List;
void swap(int& a, int& b) {
int t;
t = a;
a = b;
b = t;
}
//给定一个List传入List的大小要逆转的起始位置
void Reserve(List& list, int start, int end, int size) {
if (end <= start || end >= size) {
return;
}
int mid = (start + end) / 2;
_rep(i, 0, mid - start) {
swap(list.data[start + i], list.data[end - i]);
}
}
void PrintList(List list) {
_for(i, 0, list.length) {
cout << list.data[i] << " ";
}
cout << endl;
}
void BuildList(List& list,int Len,int Data[]) {
list.length = Len;
_for(i, 0, list.length)
list.data[i] = Data[i];
}
#pragma endregion
//P323.3
//已知线性表按顺序存储, 且每个元素都是不相同的整数型元素, 设计把所有奇数移动到
//所有偶数前边的算法(要求时间最少, 辅助空间最少)
int Partiton(List &list, int low, int high) {
int pivot = list.data[low];
while (low < high) {
while (low < high && list.data[high] % 2 == 0)
high--;
list.data[low] = list.data[high];
while (low < high && list.data[low] % 2 != 0)
low++;
list.data[high] = list.data[low];
}
list.data[low] = pivot;
return low;
}
void MoveOddNum(List& A, int low, int high) {
if (low < high) {
int pivotpos = Partiton(A, low, high);
MoveOddNum(A, low, pivotpos - 1);
MoveOddNum(A, pivotpos + 1, high);
}
}
int main()
{
List list;
int Data[] = { 1,4,9,11,14,24,32,54,62,81 };
BuildList(list, 10, Data);
cout << "排序前:" << endl;
PrintList(list);
cout << "排序后:" << endl;
MoveOddNum(list, 0, list.length - 1);
PrintList(list);
return 0;
}

View File

@@ -0,0 +1,98 @@
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <time.h>
#include <stdlib.h>
using namespace std;
#pragma region 建立顺序存储的线性表
#define MAX 30
#define _for(i,a,b) for( int i=(a); i<(b); ++i)
#define _rep(i,a,b) for( int i=(a); i<=(b); ++i)
typedef struct {
int data[MAX];
int length;
}List;
void swap(int& a, int& b) {
int t;
t = a;
a = b;
b = t;
}
//给定一个List传入List的大小要逆转的起始位置
void Reserve(List& list, int start, int end, int size) {
if (end <= start || end >= size) {
return;
}
int mid = (start + end) / 2;
_rep(i, 0, mid - start) {
swap(list.data[start + i], list.data[end - i]);
}
}
void PrintList(List list) {
_for(i, 0, list.length) {
cout << list.data[i] << " ";
}
cout << endl;
}
void BuildList(List& list, int Len, int Data[]) {
list.length = Len;
_for(i, 0, list.length)
list.data[i] = Data[i];
}
#pragma endregion
//P323.4
//试重新编写考点精析中的快速排序的划分算法, 使之每次选取的枢轴值都是随机地从当
//前子表中选择的
int Partiton(List& list, int low, int high) {
int seed = time(0);
srand(seed);
int Num = low + rand() % (high - low + 1);
swap(list.data[Num], list.data[low]);
int pivot = list.data[low];
cout << "枢轴:" << pivot << endl;
while (low < high) {
while (low < high && list.data[high] >= pivot)
high--;
list.data[low] = list.data[high];
while (low < high && list.data[low] <= pivot)
low++;
list.data[high] = list.data[low];
}
list.data[low] = pivot;
return low;
}
void QuickSort(List& A, int low, int high) {
if (low < high) {
int pivotpos = Partiton(A, low, high);
QuickSort(A, low, pivotpos - 1);
QuickSort(A, pivotpos + 1, high);
}
}
int main()
{
List list;
int Data[] = { 1,43,22,12,14,24,18,54,32,81 };
BuildList(list, 10, Data);
cout << "排序前:" << endl;
PrintList(list);
cout << "排序后:" << endl;
QuickSort(list, 0, list.length - 1);
PrintList(list);
return 0;
}

View File

@@ -0,0 +1,90 @@
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <time.h>
using namespace std;
#pragma region 建立顺序存储的线性表
#define MAX 30
#define _for(i,a,b) for( int i=(a); i<(b); ++i)
#define _rep(i,a,b) for( int i=(a); i<=(b); ++i)
typedef struct {
int data[MAX];
int length;
}List;
void swap(int& a, int& b) {
int t;
t = a;
a = b;
b = t;
}
//给定一个List传入List的大小要逆转的起始位置
void Reserve(List& list, int start, int end, int size) {
if (end <= start || end >= size) {
return;
}
int mid = (start + end) / 2;
_rep(i, 0, mid - start) {
swap(list.data[start + i], list.data[end - i]);
}
}
void PrintList(List list) {
_for(i, 0, list.length) {
cout << list.data[i] << " ";
}
cout << endl;
}
void BuildList(List& list, int Len, int Data[]) {
list.length = Len;
_for(i, 0, list.length)
list.data[i] = Data[i];
}
#pragma endregion
//P323.5
//试编写一个算法, 使之能够在数组L[1…n]中找出第小的元素(即从小到大排序后处于
//第k个位置的元素)
int Kth_Elem(List& list, int low, int high, int k) {
int pivot = list.data[low];
int low_temp = low;
int high_temp = high;
while (low < high) {
while (low < high && list.data[high] >= pivot)
high--;
list.data[low] = list.data[high];
while (low < high && list.data[low] <= pivot)
low++;
list.data[high] = list.data[low];
}
list.data[low] = pivot;
if (low == k)
return list.data[low];
else if (low > k)
return Kth_Elem(list, low_temp, low - 1, k);
else
return Kth_Elem(list, low + 1, high_temp, k);
}
int main()
{
List list;
int Data[] = { 1,4,2,13,86,24,32,125,62,21 };
BuildList(list, 10, Data);
cout << "list为" << endl;
PrintList(list);
int k = 5;
cout << "" << k << "小的元素为:" << Kth_Elem(list, 0, list.length - 1, k) << endl;
return 0;
}

View File

@@ -0,0 +1,114 @@
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <time.h>
#include <stdlib.h>
using namespace std;
#pragma region 建立顺序存储的线性表
#define MAX 30
#define _for(i,a,b) for( int i=(a); i<(b); ++i)
#define _rep(i,a,b) for( int i=(a); i<=(b); ++i)
typedef struct {
int data[MAX];
int length;
}List;
void swap(int& a, int& b) {
int t;
t = a;
a = b;
b = t;
}
//给定一个List传入List的大小要逆转的起始位置
void Reserve(List& list, int start, int end, int size) {
if (end <= start || end >= size) {
return;
}
int mid = (start + end) / 2;
_rep(i, 0, mid - start) {
swap(list.data[start + i], list.data[end - i]);
}
}
void PrintList(List list) {
_for(i, 0, list.length) {
cout << list.data[i] << " ";
}
cout << endl;
}
void BuildList(List& list, int Len, int Data[]) {
list.length = Len;
_for(i, 0, list.length)
list.data[i] = Data[i];
}
#pragma endregion
//P323.6
//〖2016统考真题】已知由n(n≥2)个正整数构成的集合A = { ak|0 ≤ k ≤ n }, 将其划分为两
//个不相交的子集A1和A2, 元素个数分别是n1和n2, A1和A2中的元素之和分别为S1和S2
//设计一个尽可能高效的划分算法, 满足|n1 - n2|最小且| S1 - S1|最大。要求
//1)给出算法的基本设计思想
//2)根据设计思想, 采用C或C++语言描述算法, 关键之处给出注释
//3)说明你所设计算法的平均时间复杂度和空间复杂度
int Partiton(List& list) {
int low = 0, low0 = 0, high = list.length - 1, high0 = list.length - 1, k = list.length / 2;
bool NoFind = true;
while (NoFind) {
int pivot = list.data[low];
while (low < high) {
while (low < high && list.data[high] >= pivot)
high--;
if (low != high)
list.data[low] = list.data[high];
while (low < high && list.data[low] <= pivot)
low++;
if (low != high)
list.data[high] = list.data[low];
}
list.data[low] = pivot;
if (low == k - 1)
NoFind = false;
else {
if (low < k - 1) {
low0 = ++low;
high = high0;
}
else {
high0 = --high;
low = low0;
}
}
}
int s1 = 0, s2 = 0;
_for(i, 0, k)
s1 += list.data[i];
_for(i, k, list.length)
s2 += list.data[i];
return s2 - s1;
}
int main()
{
List list;
int Data[] = { 1,43,22,12,14,24,18,54,32,81 };
BuildList(list, 10, Data);
cout << "list为" << endl;
PrintList(list);
cout << "排序后:" << endl;
sort(list.data, list.data + 10);
PrintList(list);
cout << "S2-S1最大值为" << Partiton(list) << endl;
return 0;
}

View File

@@ -0,0 +1,90 @@
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <time.h>
#include <stdlib.h>
using namespace std;
#pragma region 建立顺序存储的线性表
#define MAX 30
#define _for(i,a,b) for( int i=(a); i<(b); ++i)
#define _rep(i,a,b) for( int i=(a); i<=(b); ++i)
typedef struct {
int data[MAX];
int length;
}List;
void swap(int& a, int& b) {
int t;
t = a;
a = b;
b = t;
}
//给定一个List传入List的大小要逆转的起始位置
void Reserve(List& list, int start, int end, int size) {
if (end <= start || end >= size) {
return;
}
int mid = (start + end) / 2;
_rep(i, 0, mid - start) {
swap(list.data[start + i], list.data[end - i]);
}
}
void PrintList(List list) {
_for(i, 0, list.length) {
cout << list.data[i] << " ";
}
cout << endl;
}
void BuildList(List& list, int Len, int Data[]) {
list.length = Len;
_for(i, 0, list.length)
list.data[i] = Data[i];
}
#pragma endregion
//P323.7
//荷兰国旗问题:设有一个仅由红、白、蓝三种颜色的条块组成的条块序列, 请编写一个时间
//复杂度为O(m)的算法, 使得这些条块按红、白、蓝的顺序排好, 即排成荷兰国旗图案
void Flag_Arrange(List &list) {
int i = 0, j = 0, k = list.length - 1;
while (j <= k) {
switch (list.data[j]){
case 0: {
swap(list.data[i++], list.data[j++]);
break;
}
case 1:{
j++;
break;
}
case 2: {
swap(list.data[j], list.data[k--]);
}
}
}
}
int main()
{
List list;
//设红为0白为1蓝为2
int Color[] = { 1,0,1,2,2,1,2,0,1,2 };
BuildList(list, 10, Color);
cout << "排序前为:" << endl;
PrintList(list);
cout << "排序后为:" << endl;
Flag_Arrange(list);
PrintList(list);
return 0;
}

View File

@@ -0,0 +1,55 @@
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define ElemType int
#define _for(i,a,b) for(int i=(a);i<(b);i++)
//P349.2
//设顺序表用数组A[]表示, 表中元素存储在数组下标1 --- (m + n)的范围内, 前m个元素
//递增有序, 后n个元素递增有序, 设计一个算法, 使得整个顺序表有序
//1)给出算法的基本设计思想
//2)根据设计思想, 采用C/C++描述算法, 关键之处给出注释
//3)说明你所设计算法的时间复杂度与空间复杂度。
//归并排序
void MergeSort(vector<ElemType> &A, int m, int n) {
vector<ElemType> B(m + n + 1);
int i = 1, j = m + 1, k = 1;
while (i <= m && j <= m + n) {
if (A[i] < A[j]) {
B[k++] = A[i++];
}
else {
B[k++] = A[j++];
}
}
while (i <= m) {
B[k++] = A[i++];
}
while (j <= m + n) {
B[k++] = A[j++];
}
A = B;
}
void Print(vector<ElemType> A) {
for (int i = 1; i <= A.size() - 1; i++) {
cout << A[i] << " ";
}
cout << endl;
}
int main()
{
vector<ElemType> A = { -999,2,5,21,54,64,12,25,34,62,87,91 };
cout << "排序前:" << endl;
Print(A);
MergeSort(A, 5, 6);
cout << "排序后:" << endl;
Print(A);
return 0;
}

View File

@@ -0,0 +1,48 @@
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define ElemType int
//P349.3
//有一种简单的排序算法, 称为计数排序(count sorting)这种排序算法对一个待排序的表
//用数组表示)进行排序, 并将排序结果存放到另一个新的表中。必须注意的是, 表中所
//有待排序的关键码互不相同, 计数排序算法针对表中的每个记录, 扫描待排序的表一趟
//统计表中有多少个记录的关键码比该记录的关键码小, 假设针对某个记录统计出的计数
//值为c, 则这个记录在新有序表中的合适存放位置即为c
//1)设计实现计数排序的算法
//2)对于有n个记录的表, 关键码比较次数是多少 ?
//3)与简单选择排序相比较, 这种方法是否更好 ? 为什么
void CountSort(vector<ElemType> &A) {
vector<ElemType> B(A.size());
for (int i = 0; i < A.size(); i++) {
int count = 0;
for (int j = 0; j < A.size(); j++) {
if (A[j] < A[i])
count++;
}
B[count] = A[i];
}
A = B;
}
void Print(vector<ElemType> A) {
for (int i = 1; i <= A.size() - 1; i++) {
cout << A[i] << " ";
}
cout << endl;
}
int main()
{
vector<ElemType> A = { 61,2,5,21,24,64,12,15,34,32,47,9 };
cout << "排序前:" << endl;
Print(A);
CountSort(A);
cout << "排序后:" << endl;
Print(A);
return 0;
}

View File

@@ -0,0 +1,52 @@
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define ElemType int
//P350.4
//设有一个数组中存放了一个无序的关键序列K1, K2, …, Kn。现要求将Kn放在将元素排序
//后的正确位置上, 试编写实现该功能的算法, 要求比较关键字的次数不超过n。
//快排
int Partition(vector<ElemType> &A,int low,int high) {
int pivot = A[high];
while (low < high) {
while (low < high && A[low] <= pivot)
low++;
A[high] = A[low];
while (low < high && A[high] >= pivot)
high--;
A[low] = A[high];
}
A[high] = pivot;
return low;
}
void QuickSort(vector<ElemType>& A, int low, int high) {
if (low < high) {
int pivotpos = Partition(A, low, high);
QuickSort(A, low, pivotpos - 1);
QuickSort(A, pivotpos + 1, high);
}
}
void Print(vector<ElemType> A) {
for (int i = 1; i <= A.size() - 1; i++) {
cout << A[i] << " ";
}
cout << endl;
}
int main()
{
vector<ElemType> A = { 61,2,5,21,24,64,12,15,34,32,47,9 };
cout << "排序前:" << endl;
Print(A);
QuickSort(A, 0, A.size() - 1);
cout << "排序后:" << endl;
Print(A);
return 0;
}

View File

@@ -0,0 +1,116 @@
#include <iostream>
#include <vector>
using namespace std;
#define ElemType int
#define _for(i,a,b) for(int i=(a);i<(b);i++)
#define INF 0x3f3f3f3f
#pragma region 建立带头结点的链表
typedef struct LNode {
ElemType data;
struct LNode* next;
}LNode, * LinkList;
//初始化链表
bool InitList(LinkList& L) {
//分配一个头结点
L = (LNode*)malloc(sizeof(LNode));
//内存不足,分配失败
if (L == NULL) {
return false;
}
//头结点之后暂时还没有节点
L->next = NULL;
return true;
}
//判断是否为空
bool IsEmpty(LinkList L) {
return ((L->next) == NULL);
}
//使用尾插法建表
LinkList CreatList(vector<int> data) {
if (data.size() < 1) {
return NULL;
}
//头结点
LNode* head = (LinkList)malloc(sizeof(LNode));
head->data = NULL;
head->next = NULL;
LinkList p = head;
_for(i, 0, data.size()) {
LNode* s = (LinkList)malloc(sizeof(LNode));
s->data = data[i];
s->next = NULL;
p->next = s;
p = s;
}
return head;
}
//输出链表
void PrintList(LinkList list) {
if (IsEmpty(list)) {
cout << "the list is null" << endl;
return;
}
while (list != NULL) {
printf("%d ", list->data);
list = list->next;
}
printf("\n");
}
int Getlen(LinkList L) {
int len = 0;
while (L != NULL) {
L = L->next;
len++;
}
return len;
}
#pragma endregion
//P335.4
//编写一个算法, 在基于单链表表示的待排序关键字序列上进行简单选择排序
void SortList(LinkList &head) {
LinkList h = head->next;
head = NULL;
while (h) {
LinkList max = h, maxpre = NULL, pre = NULL, p = h;
while (p) {
if (p->data > max->data) {
max = p;
maxpre = pre;
}
pre = p;
p = p->next;
}
if (max == h)
h = h->next;
else
maxpre->next = max->next;
max->next = head;
head = max;
}
}
int main()
{
vector<int> data{ 3,54,26,18,34,47,19,57 };
LinkList head;
InitList(head);
head = CreatList(data);
cout << "排序前:" << endl;
PrintList(head->next);
cout << "排序后:" << endl;
SortList(head);
PrintList(head->next);
return 0;
}

View File

@@ -0,0 +1,39 @@
#include <iostream>
#include <vector>
using namespace std;
#define ElemType int
//P335.5
//试设计一个算法, 判断一个数据序列是否构成一个小根堆
bool IsHeap(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()
{
ElemType A[] = { -1,2,4,5,21,45,21,44,22,87,2,4,8 };
ElemType B[] = { -1,2,4,3 };
if (IsHeap(B, 3))
cout << "是小根堆" << endl;
else
cout << "不是小根堆" << endl;
return 0;
}