数据结构-查找和排序

查找和排序

查找

  1. 静态查找表

    • 顺序查找

      (1)对表的限制少

      (2)同时适用于顺序存储结构和链式存储结构

      (3)时间性能最差

      (4)等概率查找成功ASL:(n+1)/ 2

    • 折半查找

      (1)要求:必须是顺序存储且按关键字值有序排列

      (2)效率高

  2. 动态查找表

    • 二叉排序树
    • 平衡二叉树
  3. 哈希表

内部排序

  1. 插入类

    • 直接插入排序

      (1)稳定

      (2)时间复杂度:n^2

      (3)代码:

      void InsertionSort ( SqList &L ) {
        // 对顺序表 L 作直接插入排序。
         for ( i=2; i<=L.length; ++i ) 
             if (L.r[i].key < L.r[i-1].key) {
                 L.r[0] = L.r[i];            // 复制为监视哨
                 for ( j=i-1; L.r[0].key < L.r[j].key;  -- j )
                     L.r[j+1] = L.r[j];        // 记录后移
                 L.r[j+1] = L.r[0];        // 插入到正确位置
             }
      } // InsertSort
      
      
    • 折半插入排序

      (1)稳定

      (2)时间复杂度:nlogn

    • 希尔排序(缩小增量排序)

      (1)不稳定

      (2)时间复杂度:n*(logn)^2

      (3)代码

      void ShellInsert ( SqList &L, int dk ) {
         for ( i=dk+1; i<=n; ++i )
            if ( L.r[i].key< L.r[i-dk].key) {
              L.r[0] = L.r[i];            // 暂存在R[0]
              for (j=i-dk;  j>0&&(L.r[0].key<L.r[j].key);
                      j-=dk)
                 L.r[j+dk] = L.r[j];  // 记录后移,查找插入位置
              L.r[j+dk] = L.r[0];                // 插入
            } // if
      } // ShellInsert
      void ShellSort (SqList &L, int dlta[], int t)
      {    // 增量为dlta[]的希尔排序
           for (k=0; k<t; ++k)
               ShellInsert(L, dlta[k]);
                   //一趟增量为dlta[k]的插入排序
      } // ShellSort
      
      
  2. 交换类

    • 冒泡排序

      (1)稳定的

      (2)时间复杂度:n^2

      (3)代码

      void BubbleSort( SqList  &L ) {
          //对顺序表L作冒泡排序
            for(i=2; i<=L.length; i++) {     //进行n-1趟扫描
                  move=False ;                  //move是交换与否的标志     
                  for( j=n;  j<=i;  j- - ) 
                       if( L.R[ j ] < L.R[ j-1] ) { //如逆序则交换 
      			 L.R[ j ]↔L.R[ j-1]; //这里只是描述
      			 move=True; 
      		       }
                   if ( !move ) return;         //如果没有移动发生,则结束
             }
      } 
      
    • 快速排序

      (1)不稳定

      (2)平均时间复杂度:nlogn

      (3)代码

      int partition( SqList  &L, int low, int high )  {
          //对排序区间L.R[low..high]进行一次分区,返回基准位置下标
         pivotkey=L.R[low].key;  i=low;  j=high; L.R[0]=L.R[low];
         while( i<j ) {  
             while(j>i&&L.R[ j ].key>=pivotkey) j--;  //i指向基准,j向左扫描                              
             L.R[ i ] = L.R[ j ];                            // 比基准小的记录移到低端                            
             while(i<j&&L.R[ i ].key<=pivotkey) i++; //j指向基准,i向右扫描                              
             L.R[ j ] = L.R[ i ];                            // 比基准大的记录移到高端                            
         }
         L.R[ i ] = L.R[0];         //基准到位
         return  i;                 //返回基准的位置下标
      } 
      void  Qsort( SqList  &L, int low, int high )  {
          //对排序区间L.R[low..high]进行快速排序
            if( low < high ) {
                  pivotloc=partition( L, low, high ); //进行分区,返回基准下标                              
                  Qsort(L, low, pivotloc-1) ;         // 对左半区进行快速排序                            
                  Qsort(L, pivotloc+1, high) ;      // 对右半区进行快速排序                            
            }
      } 
      void  QuickSort( SqList  &L)  {
          // 对整个顺序表进行快速排序
            Qsort( L, 1, L.length );
      } 
      
      
  3. 选择类

    • 简单选择排序

      (1)不稳定

      (2)时间复杂度:n^2

      (3)代码

      void SelectSort( SqList  &L )  {
          //对顺序表L作简单选择排序
         for(i=1; i<L.length; i++){
      		 min=i; 
            for (j=i+1;j<=L.length;j++) //选最小的记录
               if (L.R[j].key<L.R[min].key)  min=j;
      		 if (i!=min)  L.R[min]↔L.R[i];
      			//与无序区第一条记录交换
         }//end for
      } 
      
    • 堆排序

      (1)不稳定

      (2)时间复杂度:n*logn

      (3)代码:

      void HeapAdjust ( SqList  &H,  int s,  int m )  {
          //已知H.R[s+1..m]满足大顶堆定义
          //调整H.R[s],使得H.R[s..m]成为大顶堆
         rc=H.R[s];
         for(j=2*s; j<=m; j*=2){
            if(j<m && H.R[j].key<H.R[j+1].key) j++;
            if(rc.key>=H.R[j].key) break;
            H.R[s]=H.R[j]; s=j;
         }
         H.R[s]=rc;
      }
      void HeapSort ( SqList  &H )  {
          //把H.R[1..H.length]建成大顶堆
         for (i=H.length/2; i>0; i--)
            HeapAdjust(H, i, H.length);
          //堆排序
         for(i=H.length; i>1; i--) {
            H.R[1]<->H.R[i];
            HeapAdjust(H, 1, i-1);
         }
      }
      
  4. 归并类

    • 归并排序

      (1)稳定

      (2)时间复杂度:nlogn

      (3)代码

      //递归
      void Merge(RecType SR[], RecType &TR[],
      					  int i, int m, int n){
      	//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]
      	for(j=m+1,k=i; i<=m&&j<=n; ++k){
      		if(SR[i].key<=SR[j].key) TR[k]=SR[i++];
      		else TR[k]=SR[j++];
      	}
      	if(i<=m) TR[k..n]=SR[i..m];
      	if(j<=n) TR[k..n]=SR[j..n];
      }  //end Merge
      void MSort(RecType SR[], RecType &TR1[],
      					         int s, int t){
      	//将SR[s..t]归并排序为TR1[s..t]
      	RecType TR2[n];   //定义辅助数组TR2 
        if(s==t) TR1[s] = SR[s];
      	else {
          m=(s+t)/2; //将SR[s..t]平分为SR[s..m]和SR[m+1..t]
          MSort(SR, TR2, s, m); //SR[s..m]排序成TR2[s..m]
          MSort(SR, TR2, m+1, t);//SR[m+1..t]排序成TR2[m+1..t]
          Merge(TR2, TR1, s, m, t); //两个有序的相邻区间归并
        }
      }  //end MSort
      void MergeSort(SqList &L) 
      	//对顺序表L作归并排序
      	MSort(L.r, L.r, 1, L.length); 
      }  //end MergeSort
      
      //非递归
      void  Merge(RcdType  SR[ ],  RcdType  TR[ ], int i, int m, int n) {
           //将有序的SR[i..m]和SR[m+1..n]异地归并为有序的TR[i..n]
          for (j=m+1, k=i; i<=m&&j<=n; k++) {
               if  ( SR[ i ].key<=SR[ j ].key ) TR[ k ]=SR[ i++ ]; 
               else TR[ k ]=SR[ j++ ];
          }
          if ( i<=m ) TR[ k . . n ]=SR[ i . . m ];
          if ( j<=m ) TR[ k . . n ]=SR[ j . . n ];
      }
      void  MergePass(RcdType  SR[ ],  RcdType  TR[ ], int L, int n) {
        //对SR[1..n]进行趟归并排序,结果放入TR中,L是子表的长度
         for (i=1; i+2*L-1<=n; i+=2*L) 
         Merge(SR,TR,i,i+L-1,i+2*L-1);
               //相邻子表SR[i..i+L-1]和SR[i+L..i+2*L-1]进行归并
         if(i+L-1)<n)  //还剩两个子表, 但最后一个子表长度不足L
            Merge(SR,TR,i,i+L-1,n); 
         else          //还剩一个子表,直接抄入TR
            TR[i..n]=SR[i..n];
      }
      void  MergeSort ( SqList &L ) {
           //对排序表L进行归并排序
        RcdType *TR;          
       TR=new [(sizeof(RcdType)*L.length)]; //辅助数组
       for(int L=1; L<n; L*=2){
          MergePass(L.R,TR,L,L.length);
      		           //一趟归并,结果存入TR中
          L*=2;    //将子表长度扩大一倍
          MergePass(TR,L.R,L,L.length);
                        //一趟归并,结果存入L.r中
          } //end for
          free(TR);
      }
      
  5. 其他类

    • 基数排序
  • 注意:代码中涉及一些没有写完整的部分,本文中的代码块仅仅是提供一些思路。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃胖头鱼li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值