赞
踩
实验四 查找和排序算法实现
用随机函数生成 16 个 2 位正整数(10~99),实现插入排序、希尔排序、冒泡排序、
快速排序、选择排序、堆排序、二路归并排序等多种排序算法,输出排序中间过程、统
计关键字的比较次数和记录的移动次数。
比较次数和移动次数,其实我也不懂的,经供参考
#include<iostream> #include<iomanip> #include<cstdio> using namespace std; //插入排序,从数组下标1开始 void swap(int& a, int& b) { int t = a; a = b; b = t; } void show(int* a, int n) { for (int i = 1; i <= n; i++) cout << a[i] << " "; cout << endl; } //插入排序 void insertion_sort(int* a, int n) { int compare = 0, move = 0; for (int i = 2; i <= n; i++) { int key = a[i], j = i - 1; while (j > 0 && a[j] > key) { a[j + 1] = a[j]; compare++; --j; } a[j + 1] = key; compare++; move++; cout << "第" << move << "次移动的中间过程:"; show(a, n); } cout << "关键字的比较次数:" << compare << endl; cout << "记录的移动次数:" << 3 * move << endl; } //希尔排序,将待排序序列分为若干子序列(每个子序列的元素在原始数组中间距相同); //对这些子序列进行插入排序;减小每个子序列中元素之间的间距,重复上述过程直至间距减少为 1。 void shell_sort(int* a, int n) { int compare = 0, move = 0, cnt = 0, h = 1; while (h < n / 3) h = 3 * h + 1; while (h >= 1) { for (int i = h; i < n; i++) { for (int j = i; j >= h && a[j] < a[j - h]; j -= h) { compare++; swap(a[j], a[j - h]); move++; } cnt++; cout << "第" << cnt << "次移动的中间过程:"; for (int i = 0; i < n; i++)cout << a[i] << " "; cout << endl; } h = h / 3; } cout << "关键字的比较次数:" << compare << endl; cout << "记录的移动次数:" << 3 * move << endl; } //冒泡排序,从数组下标1开始 //每次检查相邻两个元素,如果前面的元素与后面的元素满足给定的排序条件,就将相邻两个元素交换 void bubble_sort(int* a, int n) { int compare = 0, move = 0, flag = 1; while (flag) { flag = 0; for (int i = 1; i <= n - 1; i++) { if (a[i] > a[i + 1]) { flag = 1; swap(a[i], a[i + 1]); move++; cout << "第" << move << "次移动的中间过程:"; show(a, n); } compare++; } } cout << "关键字的比较次数:" << compare << endl; cout << "记录的移动次数:" << 3 * move << endl; } //双向冒泡 void debubble_sort(int* a, int n) { int compare = 0, move = 0, cnt = 0; int left = 1, right = n,shift=1; while (left < right) { for (int i = left; i < right; i++) { if (a[i] > a[i + 1]) { swap(a[i], a[i + 1]); move++; shift = i; } compare++; } right = shift; for (int i = right - 1; i >= left; i--) { if (a[i] > a[i + 1]) { swap(a[i], a[i + 1]); move++; shift = i + 1; } compare++; } left = shift; cout << "第" << ++cnt << "次移动的中间过程:"; show(a, 16); } cout << "关键字的比较次数:" << compare << endl; cout << "记录的移动次数:" << 3 * move << endl; } //快速排序 //要把数列分成两个部分,可选择一个特殊下标的值为基准,然后保证前一个子数列中的数都小于后一个子数列中的数,即是可交换 //后再分成前后两个序列,而是在分的过程中要保证相对大小关系,分别进行快速排序,且不用合并,因为此时数列已经完全有序 int quick_sort_compare = 0, quick_sort_move = 0, quick_sort_cnt = 0; void quick_sort(int* &a, int left, int right) { if (left >= right)return; int i = left, j = right, base = a[left]; while (i < j) { while (a[j] >= base && i < j)j--, quick_sort_compare++; while (a[i] <= base && i < j)i++, quick_sort_compare++; if (i < j) { swap(a[i], a[j]); quick_sort_move++; } } a[left] = a[i]; a[i] = base; cout << "第" << ++quick_sort_cnt << "次中间过程输出:"; show(a, 16); quick_sort(a, left, i - 1); quick_sort(a, i + 1, right); } //选择排序,从数组下标1开始,每次找出第 i小的元素然后将这个元素与数组第 i个位置上的元素交换。 void selection_sort(int* a, int n) { int compare = 0, move = 0; for (int i = 1; i <= n - 1; i++) { int k = i; for (int j = i + 1; j <= n; j++) { if (a[j] < a[k]) { k = j; } compare++; } if (i != k) { swap(a[i], a[k]); move++; cout << "第" << move << "次移动的中间过程:"; show(a, n); } } cout << "关键字的比较次数:" << compare << endl; cout << "记录的移动次数:" << 3 * move << endl; } //堆排序,从上往下把左右孩子和邻接根节点交换的成当前子树的根节点 int heap_sort_compare = 0, heap_sort_move = 0; void max_heapmodify(int* a, int l, int r) { int fa = l, son = 2 * fa + 1, temp = a[l]; while (son < r) { heap_sort_compare++; if (son + 1 < r && a[son] < a[son + 1])son++; heap_sort_compare++; if (a[son] < a[fa])return; //子树中较大的节点都小于当前子树的根节点 else { swap(a[son], a[fa]); //子树中最大的节点与当前子树的根节点进行交换 fa = son; //转移根节点的下标到下一层 son = fa * 2 + 1; cout << "第" << heap_sort_move++ << "次移动的中间过程:"; for (int i = 0; i < 16; i++)cout << a[i] << " "; cout << endl; } } } //堆排序,利用 "堆" 这种数据结构所设计的一种排序算法 void heap_sort(int* a, int n) { //对原数列建大根堆 for (int i = n / 2 - 1; i >= 0; i--)max_heapmodify(a, i, n); //逆序递减下标,交换堆顶元素下标为0和当前未再次调整堆最底的元素,再次重新向上调整 for (int i = n - 1; i >= 1; i--) { swap(a[0], a[i]); max_heapmodify(a, 0, i); } //for (int i = 0; i < n; i++)cout << a[i] << " "; cout << "关键字的比较次数:" << heap_sort_compare << endl; cout << "记录的移动次数:" << 3 * heap_sort_move << endl; } //二路归并排序 //把数列分划为两部分,直到数列长度为1;递归地分别对两个子序列进行交换排序;再把当前已经排好序的数列合并成一个子序列 int merge_compare = 0, merge_move = 0, merge_cnt = 0, merge_ans = 0, t[17]; void merge(int*&a,int left, int right) { if (right - left <= 1) return; int mid = (left + right) / 2; //把数列分划为两部分 merge(a,left, mid); merge(a,mid, right); cout << "第" << ++merge_cnt << "次中间过程输出:"; show(a, 16); //递归地分别对两个子序列进行交换排序 int p = left, q = mid, s = left; while (s < right) { if (p >= mid || (q < right && a[p] > a[q])) { t[s++] = a[q++]; merge_ans += mid - p; merge_move++; } else t[s++] = a[p++]; merge_compare++; } //再把当前已经排好序的数列合并成一个子序列 for (int i = left; i < right; ++i) a[i] = t[i]; } int main() { int* a = new int[18],*b=new int[18]; for (int i = 1; i <= 16; i++) { a[i] = rand() % 90 + 10; b[i] = a[i]; } cout << "插入排序:" << endl; insertion_sort(b, 16); cout << endl; for (int i = 0; i < 16; i++) b[i] = a[i+1]; cout << "希尔排序:" << endl; shell_sort(b, 16); cout << endl; cout << "冒泡排序:" << endl; for (int i = 1; i <= 16; i++) b[i] = a[i]; bubble_sort(b, 16); cout << endl; cout << "双向冒泡排序:" << endl; for (int i = 1; i <= 16; i++) b[i] = a[i]; debubble_sort(b, 16); cout << endl; cout << "快速排序:" << endl; for (int i = 1; i <= 16; i++) b[i] = a[i]; quick_sort(b,1,16); cout << "关键字的比较次数:" << quick_sort_compare << endl; cout << "记录的移动次数:" << 3 * quick_sort_move << endl; cout << endl; for (int i = 1; i <= 16; i++) b[i] = a[i]; cout << "选择排序:" << endl; selection_sort(b, 16); cout << endl; cout << "堆排序:" << endl; for (int i = 0; i < 16; i++) b[i] = a[i + 1]; b[16] = 0; heap_sort(b, 16); cout << endl; cout << "二路归并排序:" << endl; for (int i = 1; i <= 16; i++) b[i] = a[i]; merge(b, 1, 16); cout << "关键字的比较次数:" << merge_compare << endl; cout << "记录的移动次数:" << 3 * merge_move << endl; cout << "记录的逆序对的个数:" << merge_ans << endl; return 0; }
(1) 顺序查找:使用数组或链表结构。用随机函数生成 16 个不重复的字母(’a’~’z’),
键盘输入待查找的字母,返回查找成功与否,若成功则返回该字母所在的位置(序号),
并计算比较次数。
(2) 折半查找:用数组实现,查找前元素先排序。计算比较次数。分别用查找成功、
不成功进行测试。
(3) 二叉查找树:手工输入 10 个字母,生成一棵二叉查找树,用递归算法打印树结
构或分别输出先序和中序遍历序列以确认其结构。键盘输入待查找的字母,计算比较次
数,并删除该字母。分别用查找成功、不成功进行测试。
#include<iostream> #include<iomanip> #include<cstdio> #include<stdio.h> #include<stdlib.h> using namespace std; //顺序链表 struct List { char c; List* next; }*head; int compare = 0; //判断数据tc是否在顺序链表中 bool inexistence(List*& head, char tc) { bool flag = true; List* list = head->next; while (list != NULL) { if (list->c == tc) { flag = false; break; } list = list->next; } return flag; } //顺序表初始化 void sequence_init(List*& head) { List* list = head; int cnt = 0; while (1) { char tc = 'a' + rand() % 26; if (inexistence(head, tc)) { List* node = new List(); node->c = tc; list->next = node; list = node; cout << tc << " "; cnt++; } if (cnt >= 16) { break; } } list->next = NULL; cout << endl; } //顺序查找 bool sequence_search(List*& head, char tc) { List* list = head->next; bool flag = false; while (list != NULL) { compare++; if (list->c == tc) { flag = true; break; } list = list->next; } return flag; } //折半查找初始化 void binary_seacher_init(int*& a, int n) { for (int i = 1; i <= n; i++) { a[i] = rand() % 100 + 1; cout << a[i] << " "; } cout << endl; } //折半查找前需排序 void binary_seacher_sort(int*& a, int n) { for (int i = 1; i <= n - 1; i++) { int k = i; for (int j = i + 1; j <= n; j++) if (a[j] < a[k]) k = j; int temp = a[i]; a[i] = a[k]; a[k] = temp; } for (int i = 1; i <= n; i++)cout << a[i] << " "; cout << endl; } //折半查找 bool binary_search(int*& a, int n, int ta) { bool flag = false; int left = 1, right = n; while (left < right) { compare++; int mid = (left + right) >> 1; if (a[mid] == ta) { flag = true; break; } else if (a[mid] > ta) { right = mid - 1; } else if (a[mid] < ta) { left = mid + 1; } } return flag; } //二叉查找树 struct TreeNode { unsigned char c; TreeNode* left, * right; TreeNode() { left = NULL; right = NULL; } char getc() { return c; } }; //二叉查找树插入数据 TreeNode* InsertTree(TreeNode*& T, unsigned char tc) { if (T == NULL) { TreeNode* tmpNode = new TreeNode(); tmpNode->c = tc; T = tmpNode; return T; } else if (tc < T->c) T->left = InsertTree(T->left, tc); else if (tc > T->c) T->right = InsertTree(T->right, tc); return T; } //二叉查找树先序遍历 void PreOrder(TreeNode* T) { if (T != NULL) { cout << T->getc() << " "; PreOrder(T->left); PreOrder(T->right); } } //二叉查找树中序遍历 void InOrder(TreeNode* T) { if (T != NULL) { InOrder(T->left); cout << T->c << " "; InOrder(T->right); } } //二叉查找树后序遍历 void PostOrder(TreeNode* T) { if (T != NULL) { PostOrder(T->left); PostOrder(T->right); cout << T->c << " "; } } //二叉查找树查找某结点 TreeNode* binaryTree_search(TreeNode* T, unsigned char key) { compare++; if (T == NULL || T->c == key)return T; else if (T->c > key) return binaryTree_search(T->left, key); else return binaryTree_search(T->right, key); return T; } //二叉查找树查找某结点的父节点 TreeNode* binaryTree_search_father(TreeNode* T, TreeNode* fa, unsigned char key) { if (T == NULL || T->c == key)return fa; else if (T->c > key) return binaryTree_search_father(T->left, T, key); else return binaryTree_search_father(T->right, T, key); } //二叉查找树删除某结点(数据) void binaryTree_remove(TreeNode*& T, unsigned char key) { TreeNode* p = binaryTree_search(T, key); //找到需要删除的当前节点 TreeNode* fa = binaryTree_search_father(T, T, key); //找到需要删除当前节点的父节点 if (p == NULL) { cout << "删除失败"; return; } //左右子树都空 if (p->left == NULL && p->right == NULL) { if (fa->left->c == p->c)fa->left = NULL; else fa->right = NULL; delete p; } //左子树空 else if (p->left == NULL) { p->c = p->right->c; p->right = p->right->right; } //右子树空 else if (p->right == NULL) { p->c = p->left->c; p->left = p->left->left; } //左右子树都不空 else { TreeNode* pre = p, * node = p->left; //找到左子树中最右的节点 while (node->right) { pre = node; node = node->right; } if (pre == p) { p->c = node->c; p->left = node->left; } else { pre->right = node->left; p->c = node->c; } delete node; } cout << "删除成功"; } int main() { //链式顺序查找 head = new List(); head->next = NULL; cout << "顺序查询的原数组:"; sequence_init(head); char tc = 'a'; compare = 0; cout << "顺序查询\"" << tc << "\":"; if (sequence_search(head, tc)) cout << "存在,序号为:" << compare - 1 << "比较次数:" << compare; else cout << "不存在"; cout << endl; tc = 'z'; compare = 0; cout << "顺序查询\"" << tc << "\":"; if (sequence_search(head, tc)) cout << "存在,序号为:" << compare - 1 << "比较次数:" << compare; else cout << "不存在"; cout << endl; cout << endl; //折半查找 int* a = new int[11]; cout << "折半查找的原数组:"; binary_seacher_init(a, 10); cout << "折半查找排序后的数组:"; binary_seacher_sort(a, 10); int ta = 22; compare = 0; cout << "折半查找\"" << ta << "\":"; if (binary_search(a, 10, ta)) cout << "存在,比较次数:" << compare; else cout << "不存在"; cout << endl; ta = 24; compare = 0; cout << "折半查找\"" << ta << "\":"; if (binary_search(a, 10, ta)) cout << "存在"; else cout << "不存在"; cout << endl; cout << endl; //二叉查找树 //tree = new TreeNode(); TreeNode* tree = NULL; cout << "输出原始字符数据:"; //初始化二叉查找树 for (int i = 0; i < 10; i++) { char c = char('a' + rand() % 26); cout << c << " "; InsertTree(tree, c); } cout << endl; cout << "二叉查找树先序遍历:"; PreOrder(tree); cout << endl; cout << "二叉查找树中序遍历:"; InOrder(tree); cout << endl; cout << "二叉查找树后序遍历:"; PostOrder(tree); cout << endl; char key = 'b'; compare = 0; cout << "待查找的字符" << key << ":"; if (binaryTree_search(tree, key)) cout << "存在,比较次数:" << compare; else cout << "不存在"; cout << endl; key = 'd'; compare = 0; cout << "待查找的字符" << key << ":"; if (binaryTree_search(tree, key)) cout << "存在,比较次数:" << compare; else cout << "不存在"; cout << endl; key = 'n'; cout << "待删除的字符" << key << ":"; binaryTree_remove(tree, key); cout << endl; cout << "二叉查找树删除后的先序遍历:"; PreOrder(tree); cout << endl; key = 'a'; cout << "待删除的字符" << key << ":"; binaryTree_remove(tree, key); cout << endl; cout << "二叉查找树删除后的先序遍历:"; PreOrder(tree); cout << endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。