diff --git a/排序/交换排序/P323.2.cpp b/排序/交换排序/P323.2.cpp new file mode 100644 index 0000000..ff5e052 --- /dev/null +++ b/排序/交换排序/P323.2.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +using namespace std; + +#define ElemType int +#define _for(i,a,b) for(int i=(a);i<(b);i++) + +//P323.2 +//编写双向冒泡排序算法, 在正反两个方向交替进行扫描, 即第一趟把关键字最大的元素 +//放在序列的最后面, 第二趟把关键字最小的元素放在序列的最前面, 如此反复进行。 + +void BubbleSort(vector &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 A) { + _for(i, 0, A.size()) { + cout << A[i] << " "; + } + cout << endl; +} + +int main() +{ + vector A{ 2,5,21,54,64,12,65,34,12,37,21 }; + cout << "排序前:" << endl; + Print(A); + BubbleSort(A); + cout << "排序后:" << endl; + Print(A); + return 0; +} + diff --git a/排序/交换排序/P323.3.cpp b/排序/交换排序/P323.3.cpp new file mode 100644 index 0000000..ec4364a --- /dev/null +++ b/排序/交换排序/P323.3.cpp @@ -0,0 +1,91 @@ +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/排序/交换排序/P323.4.cpp b/排序/交换排序/P323.4.cpp new file mode 100644 index 0000000..0e44442 --- /dev/null +++ b/排序/交换排序/P323.4.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/排序/交换排序/P324.5.cpp b/排序/交换排序/P324.5.cpp new file mode 100644 index 0000000..10d6ece --- /dev/null +++ b/排序/交换排序/P324.5.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/排序/交换排序/P324.6.cpp b/排序/交换排序/P324.6.cpp new file mode 100644 index 0000000..4612f64 --- /dev/null +++ b/排序/交换排序/P324.6.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/排序/交换排序/P324.7.cpp b/排序/交换排序/P324.7.cpp new file mode 100644 index 0000000..e7988b4 --- /dev/null +++ b/排序/交换排序/P324.7.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/排序/内部排序的应用/P349.2.cpp b/排序/内部排序的应用/P349.2.cpp new file mode 100644 index 0000000..89f4f76 --- /dev/null +++ b/排序/内部排序的应用/P349.2.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +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 &A, int m, int n) { + + vector 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 A) { + for (int i = 1; i <= A.size() - 1; i++) { + cout << A[i] << " "; + } + cout << endl; +} + +int main() +{ + vector 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; +} + diff --git a/排序/内部排序的应用/P349.3.cpp b/排序/内部排序的应用/P349.3.cpp new file mode 100644 index 0000000..5d4cbb4 --- /dev/null +++ b/排序/内部排序的应用/P349.3.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +using namespace std; + +#define ElemType int + +//P349.3 +//有一种简单的排序算法, 称为计数排序(count sorting)这种排序算法对一个待排序的表 +//用数组表示)进行排序, 并将排序结果存放到另一个新的表中。必须注意的是, 表中所 +//有待排序的关键码互不相同, 计数排序算法针对表中的每个记录, 扫描待排序的表一趟 +//统计表中有多少个记录的关键码比该记录的关键码小, 假设针对某个记录统计出的计数 +//值为c, 则这个记录在新有序表中的合适存放位置即为c +//1)设计实现计数排序的算法 +//2)对于有n个记录的表, 关键码比较次数是多少 ? +//3)与简单选择排序相比较, 这种方法是否更好 ? 为什么 + +void CountSort(vector &A) { + vector 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 A) { + for (int i = 1; i <= A.size() - 1; i++) { + cout << A[i] << " "; + } + cout << endl; +} + +int main() +{ + vector 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; +} + diff --git a/排序/内部排序的应用/P350.4.cpp b/排序/内部排序的应用/P350.4.cpp new file mode 100644 index 0000000..65d384e --- /dev/null +++ b/排序/内部排序的应用/P350.4.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +using namespace std; + +#define ElemType int + +//P350.4 +//设有一个数组中存放了一个无序的关键序列K1, K2, …, Kn。现要求将Kn放在将元素排序 +//后的正确位置上, 试编写实现该功能的算法, 要求比较关键字的次数不超过n。 + +//快排 +int Partition(vector &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& 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 A) { + for (int i = 1; i <= A.size() - 1; i++) { + cout << A[i] << " "; + } + cout << endl; +} + +int main() +{ + vector 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; +} + diff --git a/排序/选择排序/P335.4.cpp b/排序/选择排序/P335.4.cpp new file mode 100644 index 0000000..98128a3 --- /dev/null +++ b/排序/选择排序/P335.4.cpp @@ -0,0 +1,116 @@ +#include +#include +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 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 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; +} diff --git a/排序/选择排序/P335.5.cpp b/排序/选择排序/P335.5.cpp new file mode 100644 index 0000000..972b712 --- /dev/null +++ b/排序/选择排序/P335.5.cpp @@ -0,0 +1,39 @@ +#include +#include + +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; +}