数据结构之查找与排序

查找 

 静态查找:查找时,只查找读取 

  顺序表上查找 

        无序表上查找,设置位置0为岗哨,从后往前查找,查找长度为(n+1)/2

        有序表上查找,使用二分查找,平均查找长度为 log2(n+1)-1

  索引顺序表上查找,索引表将顺序表分别分割为若干块,顺序表按块有序,查找长度为 (n/s+s)/2+1

 

 动态查找 

  二叉排序树:或为空树或具有下列性质:

       1.若左子树不为空,则左子树上的所有结点的键值均小于它的根结点的键值,

       2.若右子树不为空,则右子树上的所有结点的键值均小于它的根结点的键值,

       3.根的左子树,右子树均为二叉排序树

  中序遍历即可得到升序序列

  查找长度与树的形态有关,介于O(n)和log2(n)之间

 

  散列表:使数据的存储位置与键值之间建立某件联系,减少比较次数

       散列函数:数据元素的键值和存储位置之间建立的对应关系H

       散列表,散列地址,      

       冲突 k1!=k2 H(k1)=H(k2),则称k1,k2是相对H的同义词

       堆积:非同义词之间对同一散列地址的争夺现象 

       常用散列法:数字分析法,保留余数法,平方取中发,基数转换法

       解决冲突的方法:线性探测法 (地址+1) ,二次探测法(+-k2),链地址法,多重散列法,公共溢出区法 

排序:内部排序,外部排序 

         内部排序:插入排序,交换排序,选择排序,归并排序 

                   插入排序:直接插入排序 O(n2),折半插入排序,表插入排序,希尔排序 nlog2n n^s 

                            直接插入排序:依次将每个记录插入到一个已排好序的有序表中去,得到一个新的,记录数增加1的有序表

                            void straightInertSort(List R,int n)

                            {

                                     int i,j;

                                     for(i=2;i<n;i++)

                                     {

                                               R[0]=R[i];

                                               j=i-1;

                                               while(R[0]<R[j])

                                               {

                                                        R[j+1]=R[j];

                                                        j--;

                                               }

                                               R[j+1]=R[0];

                                     }

                            } 

                            希尔排序:以n/2为步长分割List,排序分割的List,再以原步长/2,重复执行,知道步长为0 结束排序。 

                   交换排序:冒泡排序O(n2) ,快速排序 (不稳定,nlog2n  n2) 

                            冒泡排序:是一种交换排序方法,首先将第一个记录和第二个记录比较,若为逆序,则将两个记录交换,然后比较第二个和第三个,依次类推,直到完成第n-1和第n个比较交换位置。此为第一趟起泡。结果使键值最大的记录移动到第n个位置上。然后对前n-1个记录进行同样的操作。

                            void BubbleSort(List R,int n)

                            {

                                     int i,j,temp,endSort;

                                     for(i=1;i<=n-1;i++)

                                     {

                                               endSort=0;

                                               for(j=1;j<=n-1-i;j++)

                                               {

                                                        if(R[j].key>R[j+1].key)

                                                        {

                                                                 temp=R[j];

                                                                 R[j]=R[j+1];

                                                                 R[j+1]=temp;

                                                                 endSort=1;

                                                        }

 

                                               }

                                               if(endSort==0)break;

                                     }

                            }

                            快速排序:

                            void QuickSort(List R,int low,int high)

                            {

                                     if(low<high)

                                     {

                                               temp=QuickPartition(R,low,high);

                                               QuickSort(R,low,temp-1);

                                               QuickSort(R,temp+1,high);

                                     }

                            } 

                            int QuickPartition(List R,int low,int high)

                            {

                                     x=R[low];

                                     while(low<high)

                                     {

                                               while(low<high&&R[high].key>x.key)

                                               {

                                                        high--;

                                               }

                                               R[low]=R[high];

                                               while(low<high&&R[low].key<x.key)

                                               {       

                                                        low++;

                                               }

                                               R[high]=R[low];

                                     }

                                     R[low]=x;

                                     return low;

                            } 

                   选择排序:直接选择排序(不稳定 O(n^2)),堆排序(不稳定 nlog2n) 

                            直接选择排序:在第i次选择操作中,通过第n-i次键值比较,从n-i+1个记录中,选出最小的键值记录,并和第i个记录交换。

                            void SelectSort(List R,int n)

                            {

                                     int min,i,j

                                     for(i=1;i<=n-1;i++)

                                     {

                                               min=i;

                                               for(j=i+1;j<=n;j++)

                                               {

                                                        if(R[j].key<R[min].key) min=j;

                                                        if(min!=i) swap(R[min],R[i]);

                                               }

                                     }

                            } 

                            堆排序:最小堆是一颗以k1为根的完全二叉树,任一结点都不大于它的两个孩子的值。

                            void HeapStort(List R,int n)

                            {

                                     int i;

                                     for(i=n/2;i>=1;i++)

                                               Shit(R,i,n);

                                     for(i=n;i>=2;i--)

                                     {

                                              Swap(R[1],R[i]);

                                               Shit(R,1,i-1);

                                     }

                            } 

        List为完全二叉树 顺序结构存储

        K为 根结点序号

        m为 顺序存储结构最后一个结点位置

                            void Shit(List R,int k,int m)

                            {

                                     int i,j,x;

                                     List t;

                                     i=k;j=i*2;

                                     x=R[k].key;

                                     t=R[k];

                                     while(j<=m)

                                     {

                                               if(j<m)&&R[j].key>R[j+1].key)

                                               {

                                                        j++;

                                               }

 

                                               if(x<R[j].key) break;

                                               else

                                               {

                                                        R[i]=R[j];

                                                        i=j;

                                                        j=2*i;

                                               }

                                     }

                            } 

                   归并排序:有序序列的归并(不稳定的 nlog2n),二路归并排序(稳定的 nlog2n)

                            要求待排序序列是有若干有序子序列组成 

                            有序序列的归并: a h m n

                            二路归并排序:有n个有序的子序列,每个序列的长度为1,首先将相邻的两个记录合并,得到较大的n/2个较大的有序子序列,再将相邻的子序列两两合并,得到[[n/2]/2]个有序的子序列,如此反复,直到得到一个长度为n的有序序列位置。 

         排序算法中,没有那种是最优的,就时间复杂度而言,比较简单的排序算法,直接插入,直接选择,冒泡排序等,所需时间复杂度为O(n^2).但是在某些情况下,如初始序列已基本有序,直接插入算法和冒泡算法时间复杂度为O(n)。就待排序列的记录数量而言,当记录数较小时,尽量选择简单的排序算法,当n比较大时并且记录无规律可言时,采用快速排序,堆排序,归并排序等时间复杂度较低的算法。快速排序,直接选择排序,堆排序是不稳定的算法。

posted @ 2016-03-31 15:22  欣欣点灯  阅读(565)  评论(0编辑  收藏  举报