考研数据结构--排序汇总(自用)
1、插入排序:
1)直接插入排序:
哨兵版:
void insertSort(int A[], int n)
{int i, j;for(i = 2; i <= n; i++){A[0] = A[i]; //负责为哨兵,A[0]不存放元素 for(j = i - 1; A[0] < A[j]; j--)A[j+1] = A[j];A[j+1] = A[0];}
}
普通版:
void insertSort2(int A[], int n)
{int i, j;int temp; for(i = 1; i < n; i++){//A[0]放元素if(A[i] < A[i-1]) {temp = A[i]; //暂存A[i];for(j = i-1; j >= 0 &&A[j] > temp; --j)A[j+1] = A[j];A[j+1] = temp;} }
}
2)折半插入排序:在排好的序的部分折半查找插入位置
void insertSort3(int A[], int n)
{int i,j,low,high,mid;for(i = 2; i <= n; i++){A[0] = A[i];low = 1; high = i - 1;while(low <= high){mid = (low + high)/2;if(A[mid] > A[0]) high = mid - 1;else low = mid+1;}for(j = i-1; j >= low; --j){//low指向要插入的位置low==high+1 A[j+1] = A[j];} A[low] = A[0];}
}
2、希尔排序:
严版:
void shellInsert(int A[],int n,int dk)
{int i, j;for(i = 1+dk; i <= n; i++){//对增量为dk的序列进行直接插入排序 if(A[i] < A[i-dk]){A[0] = A[i]; //暂存A[i]非哨兵,A[0]不存放元素;也可用temp代替 for(j = i-dk; j > 0 && A[0] > A[j]; j -= dk)A[j+dk] = A[j];A[j+dk] = A[0]; }}
}void shellSort(int A[], int n, int delta[], int t)
{//A为待排序列,n为其长度,delta为增量序列,t为其长度 for(int k = 0; k < t; k++){//一个增量一趟 shellInsert(A, n, delta[k]);}
}
3、冒泡排序:
void swap(int &a,int &b)
{int temp = a;a = b;b = temp;
}void bubbleSort(int A[], int n)
{//升序,从后往前冒 for(int i = 0; i < n-1; i++){bool flag = false; //本趟是否发生过交换 for(int j=n-1; j > i; j--){if(A[j] < A[j-1]){swap(A[j], A[j-1]);flag = true; }}if(flag == false) //没有交换过,则已是升序 return ;}
}
4、快速排序:找到的所有版本,区别就是partition
1)初始版本:
#include<iostream>using namespace std;
int partition(int A[],int low,int high)
{int pivotkey = A[low]; //选左边第一个pivotkey int start = low; //暂存pivotkey的下标 while(low < high){while(low < high && A[high] >= pivotkey) high--;while(low < high && A[low] <= pivotkey) low++;if(low < high){swap(A[low],A[high]);} }swap(A[low],A[start]); //此时low == high,且A[low]必然是小于等于pivotkey的 return low;
}
void QSort(int A[], int low, int high)
{if(low < high){int pivotloc = partition(A, low, high);QSort(A, low, pivotloc-1);QSort(A, pivotloc+1, high);}
}
void QuickSort(int A[], int n)
{QSort(A,0,n-1);
}
int main()
{int A[10] = {4,2,1,4,5,6,7,8,9,3}; QuickSort(A,10);for(int i = 0; i < 10; i++){cout<<A[i]<<endl;}return 0;
}
2)挖坑法:对上面的改进,严书上只有这个(但是暨大考过其他版本的,所以汇总下)
#include<iostream>
using namespace std;
int partition(int A[],int low,int high)
{int pivotkey = A[low];while(low < high){while(low < high && A[high] >= pivotkey) high--;A[low] = A[high];while(low < high && A[low] <= pivotkey) low++;A[high] = A[low];}A[low] = pivotkey;return low;
}
3)前后指针法:
最右边的枢纽:
int partition(int A[],int low,int high)
{int pivotkey = A[high]; //最右边为枢纽int i = low - 1;for(int j = low; j <= high-1; j++){if(A[j] < pivotkey){i++;swap(A[i], A[j]); }} swap(A[i+1],A[high]); //[low,i]、i+1、[i+2,high] return i+1;
}
最左边的为枢纽:
int partition(int A[],int low,int high)
{int pivotkey = A[low]; //最左边为枢纽int i = high+1;for(int j = high; j > 0; j--){if(A[j] > pivotkey){i--;swap(A[i], A[j]); }} swap(A[i-1],A[low]); //[low,i]、i+1、[i+2,high] return i-1;
}
王道这样写的,感觉好点
int partition(int A[],int low,int high)
{int pivotkey = A[low]; //最左边为枢纽int i = low;for(int j = low+1; j <= high; j++){if(A[j] < pivotkey){swap(A[++i], A[j]); }} swap(A[i],A[low]);return i;
}
随机位置:
int partition(int A[], int low,int high)
{int random_index = rand()%(high-low+1);swap(A[low],A[random_index]);int pivotkey = A[low];while(low < high){while(low < high && A[high] >= pivotkey)high--;A[low] = A[high]; while(low < high && A[low] <= pivotkey) low++;A[high] = A[low];} A[low] = pivotkey;return low;
}
int partition(int A[], int low, int high)
{int random_index = rand()%(high-low+1);swap(A[low],A[random_index]);int pivotkey = A[low];int i = low;for(int j = low+1;j <= high; j++){if(A[j] < pivotkey){swap(A[++i],A[j]);}}swap(A[i],A[low]);return i;
}
暨大考题2020:填空
int partition(int* A, int N, int p, int r)
{ int x = A[r];int i = //(5) ;for (int j = p; j<=r-1; j++){if ( //(6) ){i = i + 1;int temp = A[i];A[i] = A[j];A[j] = temp;}}int temp = A[i+1];A[i+1] = A[r];A[r] = temp;return //(7) ;
}
void QuickSort(int* A, int N, int p, int r)
{int q;if ( //(8) ){q = partition(A, N, p, r);QuickSort( //(9) );QuickSort( //(10) );}return;
}
void main()
{ QuickSort(A, N, 0,N-1);return 0;
}
4)Hoare分区方案:第1个版本的另一种写法
int partition(int arr[],int low, int hight)
{int pivot = arr[low]; int i = low - 1;int j = hight + 1; while(true){while(arr[++i] < pivot); //找 >= pivot的 while(arr[--j] > pivot); //找 <= piovt的if(i >= j){return j;} swap(arr[i],arr[j]);}
}
5)非递归版本:分区用哪个版本无所谓
#include<iostream>
#include<stack>using namespace std;int partition(int A[],int low,int high)
{int pivotkey = A[low];while(low < high){while(low < high && A[high] >= pivotkey) high--;A[low] = A[high];while(low < high && A[low] <= pivotkey) low++;A[high] = A[low];}A[low] = pivotkey;return low;
}
void QSort(int A[], int low, int high)
{stack<int>stk;if(low < high){stk.push(low); //先左后右进栈,先右后左出栈 stk.push(high);while(!stk.empty()){int right = stk.top(); stk.pop();int left = stk.top(); stk.pop();int pivotloc = partition(A,left, right); //枢纽下标 if(left < pivotloc - 1){//左边还有两个及以上的元素 stk.push(left); stk.push(pivotloc-1);}if(right > pivotloc + 1){//左边还有两个及以上的元素 stk.push(pivotloc+1);stk.push(right); }}}
}
void QuickSort(int A[], int n)
{QSort(A,0,n-1);
}
int main()
{int A[10] = {4,2,1,4,5,6,7,8,9,3}; QuickSort(A,10);for(int i = 0; i < 10; i++){cout<<A[i]<<endl;}return 0;
}
队列版:
void QSort(int A[], int low, int high)
{queue<int>q;if(low < high){q.push(low); q.push(high);while(!q.empty()){int left = q.front(); q.pop();int right = q.front(); q.pop();int pivotloc = partition(A,left, right); //枢纽下标 if(left < pivotloc - 1){//左边还有两个及以上的元素 q.push(left); q.push(pivotloc-1);}if(right > pivotloc + 1){//左边还有两个及以上的元素 q.push(pivotloc+1);q.push(right); }}}
}
快排扩展:第k小的数
int kth_elem(int A[],int low, int high, int k)
{int pivot = A[low];int left = low;int right = high;while(left < right){while(left < right && A[right] >= pivot) right--;A[left] = A[right];while(left < right && A[left] <= pivot) left++;A[right] = A[left];}A[left] = pivot; //left == right//上面和快排分区没什么不同if(left == k){return A[left];}else if(left > k){return kth_elem(A, low, left-1, k);} else{return kth_elem(A, left+1, high, k); }
}
5、堆排序:
顺序存储的完全二叉树下标
- 从
0
开始时,n
个结点,最大分支结点编号是((n-1)-1)/2
,双亲编号是(i-1)/2
,都是向下取整. - 从
1
开始时,n
个结点,最大分支结点编号是n/2
,双亲编号是i/2
,都是向下取整。
基于大根堆:下标从1开始
void HeapAdjust(int A[], int k, int len)
{//自顶向下调整siftDownA[0] = A[k];for(int i = 2*k; i < len; i*=2){if(i < len && A[i] < A[i+1]){i++; //取较大的子女下标 }if(A[0] >= A[i]) break;A[k] = A[i];k = i;} A[k] = A[0];
}
void BuildMaxHeap(int A[], int len)
{//建堆 for(int i = len/2; i > 0; i--){//len/2是编号最大的分支结点 HeapAdjust(A, i, len);}
}
void HeapSort(int A[], int len)
{BuildMaxHeap(A,len); //建立初始大根堆for(int i = len; i > 1; i--){swap(A[i], A[1]); //输出堆顶元素(输出到堆底) HeapAdjust(A, 1, i-1); //调整,把剩下的i-1个元素组成堆 }
}
小根堆:下标从0开始(多写了,加了插入和删除,如果只是用小根堆来排序不用写这么麻烦)
const int heapSize = 50;
typedef int HElemType;
typedef struct {HElemType elem[heapSize]; int curSize;
}minHeap;void siftDown(minHeap &heap, int i, int n)
{HElemType cur = heap.elem[i]; //i是双亲,j是i的值更小的子女 for(int j = 2*i+1; j < n; j = 2*j +1){if(j < n-1 && heap.elem[j] > heap.elem[j+1]) j++; //有右兄弟,且右兄弟更小if(cur <= heap.elem[j]) break; //双亲比子女更小,停止向下 else{heap.elem[i] = heap.elem[j]; //双亲比子女 i = j;} } heap[i] = cur;
}
viod siftUp(minHeap &heap, int start)
{//自底向下调整小根堆HElemType cur = heap.elem[start];int j = start; //j是子女int i = (j-1)/2; //i是j的双亲 while(j > 0){if(heap.elem[i] <= cur) break; //双亲更小停止向上else{heap.elem[j] = heap.elem[i]; //双亲比子女大,让子女上去(把双亲拉下来) j = i; //上一层 i = (i-1)/2; //上一层 } } heap.elem[j] = cur;
}
void insert(minHeap &heap, int x)
{if(heap.curSize == heapSize) return false;heap.elem[heap.curSize] = x;siftUp(heap,heap.curSize);heap.curSize++; return true;
}
void delete(minHeap &heap, int &x)
{//删除堆顶元素,并赋值给xif(heap.curSize == 0) return false;x = heap.elem[0]; heap.elem[0] = heap.elem[--heap.curSize];siftDown(heap, 0, heap.curSize);return true;
}
void creatMinHeap(minHeap &heap, ElemType arr[], int n)
{//创建小根堆 for(int i = 0; i < n; i++) heap.elem[i] = arr[i];heap.curSize = n;for(int i = (n-2)/2; i >= 0; i--){siftDown(heap, i, heap.curSize);}
}
HElemType* heapSort(minHeap heap)
{HElemType *res = new HElemType[heap.curSize];int j = 0;for(int i = heap.curSize-1; i >= 0; i--){res[j++] = heap.elem[0];swap(heap.elem[i],heap.elem[0]);siftDown(heap, 0, i); } //heap不是小根堆了 return res;
}
判断是不是小根堆:
bool isMinHeap(int A[], int len)
{if(len%2 == 0) //len为偶数有一个单分支结点且是编号最大的分支结点 {if(A[(len-2)/2] > A[len-1]){return false; }for(int i = (len-2)/2-1; i >= 0; i--){if(A[i] > A[2*i+1] || A[i] > A[2*i+2]){return false;}}} else{for(int i = (len-2)/2; i >= 0; i--){if(A[i] > A[2*i+1] || A[i] > A[2*i+2]){return false;}}}
}
6、归并排序:
以前写的:归并排序
迭代版本:
void MergeSort(int arr[],int len)
{int *a = arr;int *b = new int[len]; //辅助数组 for(int seg=1; seg < len; seg += seg){for(int start = 0; start < len; start += seg*2){int low = start, mid = min(start+seg, len), high = min(start+seg*2,len);int k = low;int start1 = low, end1 = mid;int start2 = mid, end2 = high;while(start1 < end1 && start2 < end2)b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];while(start1 < end1) b[k++] = a[start1++];while(start2 < end2)b[k++] = a[start2++];}int *temp = a; //交换a和b的指向,让b下一轮还是指向辅助数组 a = b; //交换会让arr和辅助数组的地位在下一轮中互换 b = temp; //而每轮循环结束后,a都指向本轮归并结果数组 }//结束上面语句后a指向的是排序后的数组,但因为arr和一开始的辅助数组角色互换//所以,如果 a != arr就说明最后一轮arr是被当作辅助数组用的//注:arr的指向是不会变的 if(a != arr){for(int i = 0; i < len; i++){b[i] = a[i]; //或者写成arr[i] = a[i];} b = a; } delete [] b;
}
递归版本:
void Merge(int A[], int temp[], int low, int mid, int high)
{for(int k = low; k <= high; k++){temp[k] = A[k];}for(int i = low, j= mid + 1, k = i;i <= mid&&j <=high; k++){if(temp[i] <= temp[j]) A[k] = B[i++];else A[k] = B[j++]; } while(i <= mid) A[k++] = temp[i++];while(j <= high) A[k++] = temp[j++];
}
void MSort(int A[],int temp[],int low,int high)
{if(low < high){int mid = (high - mid)/2;MSort(A, temp, low, mid);MSort(A, temp, mid+1, high);Merge(A, temp, low, mid, high);}
}
void MergeSort(int A[], int low, int high, int n)
{int *temp = new int[n];MSort(A, temp, low, high);
}
7、基数排序:
基数排序分两种:最高位优先MSD(Most Significant Digit first)和最低位优先LSD(Least Significant Digit first),MSD应该不考,以后再看,下面代码基于LSD.
#include<iostream>
#include<queue>using namespace std;int power(int di)
{int res = 1;for(int i = 0; i < di; i++) res *= 10;return res;
}
void print(int A[],int len)
{for(int i = 0; i < len; i++){cout<<A[i]<<" ";} cout<<endl;
}
void RadixSort(int A[], int len, int d)
{//print(A,len);queue<int>qarr[10];for(int i = 0; i < d; i++){//分配 int pow = power(i);for(int j = 0; j < len; j++){ int index = A[j]/pow% 10;qarr[index].push(A[j]); }//收集,按qarr[0]、qarr[1].....收集结果为升序,反之为降序int k = 0;for(int j = 0; j < 10; j++) {while(!qarr[j].empty()){int cur = qarr[j].front(); qarr[j].pop();A[k++] = cur;}}} //print(A,len);
}
int main()
{int A[10] = {105,12, 3, 45,47, 31, 5,6,9,567};RadixSort(A,10,3);return 0;
}
注:上面代码不能处理负数情况,负数应该也不考
可以参考
考研数据结构--排序汇总(自用)相关推荐
- 考研[*数据结构*]学习笔记汇总(全)
文章目录: 一:预备阶段 二:基础阶段笔记 三:冲刺阶段笔记 四:各章节思维导图 五:题库 来源:王道计算机考研 数据结构 一:预备阶段 之前的数据结构笔记 数据结构--学习笔记--入门必看[建议收藏 ...
- 数据结构 排序【简单排序(冒泡、插入)、希尔排序、堆排序、排序方法的综合比较、2套 排序汇总代码】
目 录 第9章 排序(上) 9.1 简单排序(冒泡.插入) 1.前提 2.简单排序(冒泡排序) 3.简单排序(插入排序) 4.时间复杂度下界 9.2 希尔排序 9.3 堆排序 排序方法综合比较 排 ...
- 北航计算机学院往年夏令营+考研面试题目汇总
北航计算机学院硕士复试机经+面经: 北航计算机学院往年夏令营+预推免机试题目汇总 北航计算机学院往年夏令营+考研面试题目汇总 北航计算机学院往年夏令营+考研面试数理题目汇总 以下是我在网络上找到的北航 ...
- (王道408考研数据结构)第五章树-第四节2:平衡二叉树(AVL)及其旋转
文章目录 一:AVL树基本概念 二:AVL树实现原理 (1)构建AVL树 (2)构建演示 (3)旋转方法 A:右单旋转调整(插入到较高左子树左侧) B:左单旋转调整(插入到较高右子树右侧) C:先左后 ...
- 计算机考研数据结构算法模板
计算机考研数据结构算法模板 前言 临近考研,想给考研党们分享一些比较通用的算法模板,让复习更高效一点.如果备考时间足够长,备考人应该有大量时间刷大量习题,会有自己总结的算法模板,笔者文章参考了王道考研 ...
- 厦门大学计算机科学专业,2018厦门大学计算机科学系考研招生信息汇总
原标题:2018厦门大学计算机科学系考研招生信息汇总 选择决定命运,成败在于坚持,既然选择了考研,说什么也别放弃,其实成功就是在艰难时刻的最后一次坚持!为了帮助2018年准备考研的备考生们尽快进入复习 ...
- 考研数据结构填空题整合_做题版
考研数据结构填空题整合 目录 考研数据结构填空题整合 一.ZYL组 ZYL组一 ZYL组二 ZYL组三 ZYL组四 ZYL组五 ZYL组六 ZYL组七 ZYL组八 二.TJP组 TJP组一 TJP组二 ...
- 二、考研数据结构笔记——绪论(理解数据结构,算法,时间复杂度计算做题技巧)
一.数据结构基本概念 1.数据:数据是信息的载体.客观事物的一种表现形式.万事万物都能用数据表示出来. 2.数据元素:数据元素是数据的基本单位,一个数据元素有若干个数据项组成 3.数据项:构成数据元素 ...
- 考研数据结构判断题整合
考研数据结构判断题整合 目录 考研数据结构判断题整合 一.ZYL组 ZYL组一 ZYL组二 ZYL组三 ZYL组四 ZYL组五 ZYL组六 ZYL组七 ZYL组八 二.TJP组 TJP组一 TJP组二 ...
最新文章
- PostgreSQL 数据库备份
- Windows下各个盘中的文件夹属性变为隐藏,怎么取消隐藏属性
- 三步在MacOS Anaconda安装ligthGBM
- go mysql use 问题,Go语言使用MySql的方法
- 比拼 Kafka, 大数据分析新秀Pulsar到底好在哪
- matlab 样本均值,Matlab | Matlab从入门到放弃(4)——样本均值
- Python 分析在德的中国程序员,告别 996 ?
- 信念很简单,把书念下去,然后走出去,不枉活一世 —转自动化所一篇博士论文致谢...
- ubuntu上搭建wiki系统
- web实现全景图的交互展示
- 估计值与平均值的离差平方和_各变量值与其算术平均数的离差平方之和为()
- HTTP协议有关知识
- 南理工计算机专业好吗,吉大计算机or南理工计算机?(江苏考生)
- python基础什么是函数的定义及用法
- 微信小程序地图图标controltap
- iOS开发中Touch ID的使用
- 【国际】塞拉利昂重点发展国家区块链计划
- 我要写王者荣耀类游戏的网页代码
- 佟丽娅现身活动火力全开 黑色裹身裙时髦大气,未修图也美的惊艳
- the unfamiliar words and sentences of《The Great Gatsby》1
热门文章
- 自学python考哪些证书-【经验分享】想转行学python,过来人提醒大家几点
- python编程教学软件-编程教学平台的python编辑器的开发
- python画图代码大全-Python实现画图软件功能方法详解
- python3入门代码-Python3 入门教程 简单但比较不错
- 一张图学会python应用到excel-Python应用之------Excel操作
- python语言的读法-Python语言的特点及自学建议
- 什么是车联网?导航?听歌?智能语音识别?事实没这么简单!
- QYResearch回顾:2017年中国汽车语音识别系统产量为1413万
- 谷歌称语音识别是下一个机会,尤其在发展中国家
- heroku创建linux主机,将Yesod部署到Heroku,无法静态构建