数据结构算法排序,查找。顺序查找、折半查找、分块查找、二叉树查找、哈希查找,插入排序、冒泡排序、归并排序、快速排序、希尔排序
1.顺序查找
顺序查找的查找过程为:从表的一端开始,依次将记录的关键字与给定的值进行比较,若某个记录的关键字和给定的值相等,则查找成功;反之,若扫描整个表后,仍未找到关键字和给定值相等的记录,则查找失败。时间复杂度O(n)。
int Search(SSTable ST,KeyType key)
{//在顺序表ST中顺序查找其关键字等于key的数据元素
for(i=ST.length;i>=1;--i)
if(ST.R[i].key==key) return i;
return 0;
}
2.折半查找
折半查找也称二分查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中的元素按关键字有序排列。查找过程:从表的中间记录开始,如果给定值和中间记录的关键字相等,则查找成功;如果给定值大于或者小于中间记录的关键字,则在中大于或小于中间记录的那一半中查找,这样重复操作,直到查找成功,或者在某一步中查找区间为空,则代表查找失败。时间复杂度为O(log2n).
int Search(SSTable ST,KeyType key)
{//在顺序表ST中顺序查找其关键字等于key的数据元素
low=1;high=ST.length;
while(low<=high)
{mid=(low+high)/2;
if(key==ST.R[mid].key) return mid;
else if (key
3.分块查找
分块查找又称索引顺序查找,这是一种性能介于顺序查找和折半查找之间的一种查找方式。在此查找方法中,除表本身以外,尚需建立一个“索引表”。将n个数据元素"按块有序"划分为m块(m ≤ n)。每一块中的结点不必有序,但块与块之间必须"按块有序";即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素,以此类推。
● 先选取各块中的最大关键字构成一个索引表;
● 先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;然后,在已确定的块中用顺序法进行查找。
4.二叉排序树查找
算法步骤①若二叉排序树为空,则查找失败,返回空指针
②若二叉排序树非空,将给定值key与根节点的关键字T->data.key进行比较;
●若key等于T->data.key,则查找成功,返回根节点地址。
●若key小于T->data.key,则递归查找左子树。
●若key大于T->data.key,则递归查找右子树。
BSTree SearchBST(BSTree T,KeyType key)
{//在根指针T所指二叉排序树中递归的查找某关键字等于key的数据元素
//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针。
if((!T)||key==T->data.key) reyurn T; //查找结束
else if(keydata.key) return SearchBST(T->lchird,key);
else return SearchBST(T->rchird,key);
}
5.哈希查找
哈希查找也称为散列查找。所谓的哈希其实就是在记录的存储位置和记录的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。查找时,根据这个确定的对应关系找到给定值的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。哈希技术既是一种存储方法,也是一种查找方法。见此博客 https://blog.csdn.net/CHENYUFENG1991/article/details/50678878
1.插入排序
(一)直接插入排序
直接插入排序是一种最简单的排序方法,其基本操作是将一条记录插入到已排好序的有序表中,从而得到一个新的、记录数量增1的有序表。
void InsertSort(SqList &L)
{//对顺序表L做直接插入排序
for(i=2;i<=L.length;++i)
if(L.r[i].key
(二)折半插入排序
①设待排序的记录存放在数组r[1…n]中,r[1]是一个有序数列。
②循环n-1次,每次使用折半查找法,查找r[i]在已排好序的序列r[1…i-1]中的插入位置,然后将r[i]插入表长为i-1的有序序列r[1…i-1],直到将r[n]插入表长为n-1的有序序列中。
void BInsertSort(SqList &l)
{
for(i=2;ihigh+1;--j) L.r[j+i]=L.r[j];
L.r[high+i]=L.r[0];
}
}
2.冒泡排序
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
void BubbleSort(Sqlist &L)
{
m=L.length-1;flag=1;
while ((m>0)&&(flag==1))
{
flag=0;
for(j=1;j<=m;j++)
if(L.r[j].key>L.r[j+1].key)
{
flag=1;
t=L.r[j];L.r[j]=L.r[j+1];
L.r[j=1]=t;
}
--m;
}
}
3.归并排序
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
如 设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11;
逆序数为14;
void MSort(RecordType R[],RecordType R[],int low,int high) {
if(low==high) T[low] = R[low];
else
{ m=(low+high)/2;
MSort(R,S,low,mid);
MSort(R,S,m+1,high);
Merge (S,T,low,mid,high);
}
}
void MergeSort(Sequence_List &L) {
MSort(L.r,L.r,1,L.length)
}
4.快速排序
快速排序是由冒泡排序改进而得到的,快速排序方法中一次交换可消除多个逆序。
(1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
(2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
(3)从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j] 和A[i]的值交换;
(4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和 A[j]的值交换;
(5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
void sort(int *a, int left, int right)
{
if(left >= right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/
{
return ;
}
int i = left;
int j = right;
int key = a[left];
while(i < j) /*控制在当组内寻找一遍*/
{
while(i < j && key <= a[j])
/*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升
序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/
{
j--;/*向前寻找*/
}
a[i] = a[j];
/*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是
a[left],那么就是给key)*/
while(i < j && key >= a[i])
/*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,
因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/
{
i++;
}
a[j] = a[i];
}
a[i] = key;/*当在当组内找完一遍以后就把中间数key回归*/
sort(a, left, i - 1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/
sort(a, i + 1, right);/*用同样的方式对分出来的右边的小组进行同上的做法*/
/*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/
}
5.希尔排序 6.选择排序
希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序。
算法步骤:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2void ShellPass(SeqList R,int d)
{//希尔排序中的一趟排序,d为当前增量
for(i=d+1;i<=n;i++) //将R[d+1..n]分别插入各组当前的有序区
if(R.key
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)。int main()
{
int i,j,t,a[11]; //定义变量及数组为基本整型
printf("请输入10个数:\n");
for(i=1;i<11;i++)
scanf("%d",&a[i]); //从键盘中输入要排序的10个数字
for(i=1;i<=9;i++)
for (j=i+1;j<=10;j++)
if(a[i]>a[j]) //如果前一个数比后一个数大,则利用中间变量t实现两值互换
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
printf("排序后的顺序是:\n");
for(i=1;i<=10;i++)
printf("%5d", a[i]); //输出排序后的数组
printf("\n");
return 0;
}