数据结构——排序查找算法实现

排序和查找算法实现

 

前面转载了一篇讲排序算法的文章,这几天将排序和查找算法进行了实现,在这里贴出代码来。

 

1.      插入排序

插入排序——直接插入排序:将一个记录插入到已排序好的有序表中,就像打扑克牌揭到牌后插入在特定位置。

#include<iostream>
using namespace std;
void sort(int a[],int n)      //插入排序算法
{
         inti,j,temp;         //定义循环变量i,j以及临时变量temp
         for(i=1;i<n;i++)     //依次将数组中每一个a[i]插入到适当位置
         {
                   j=i-1;
                   temp=a[i];
                   while(temp<a[j])
                   {  
                            a[j+1]=a[j];   //交换a[j]往后移动
                            j--;
                   }
 
                   a[j+1]=temp;
 
/*     for(int i=0;i<n;i++)      //这里为了便于理解,打印出了每次for循环后的结果
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
*/              
         }
        
}
 
void print(int *a, int n)      //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
 
}
int main()
{
         inta[]={43,1,9,54,32,17,88,24,72,48};
 
         print(a,10);
         sort(a,10);
         print(a,10);
 
         return 0;
}

下面这个冒泡排序代码和插入排序很相似

#include<iostream>
using namespace std;
void sort(int a[],int n)      //冒泡排序算法
{
         inti,j,temp;         //定义循环变量i,j以及用于交换的临时变量temp
         for(i=1;i<n;i++)     //依次将数组中每一个a[i]插入到适当位置
         {
                   for(j=0;j<i;j++)
                   {
                            if(a[j]>a[i])
                            {
                                     temp=a[j];         //交换a[j]与a[i]
                                     a[j]=a[i];
                                     a[i]=temp;
                            }
 
                   }
 
/*     for(inti=0;i<n;i++)       //这里为了便于理解,打印出了每次for循环后的结果
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
*/              
         }
        
}
 
void print(int *a, int n)        //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
 
}
int main()
{
         inta[]={43,1,9,54,32,17,88,24,72,48};
 
         print(a,10);
         sort(a,10);
         print(a,10);
 
         return 0;
}

2.      插入排序——希尔排序

插入排序——希尔排序:将一个序列分成多次进行直接插入排序,当步长为1的时候,就是直接插入排序。

#include<iostream>
using namespace std;
 
void sort(int a[],int n)          //希尔排序算法
{   
         inti,j,k,h,temp;         //定义循环变量i,j和数组下标变量k以及用于交换的临时变量temp,h为步长
 
         for(h=n/2;h>0;h=h/2)     //h为序列分组步长,下一次步长是上一次的一半
         {
                   for(i=0;i<n/h;i++)            //依次插入数组中每一个数a[i],步长为h,循环n/h次就将数组遍历完了
                   {
                            k=i;                 //每次开始时,记录下标到k
                            for(j=i;j<n;j=j+h)   //j每次增加步长h,即序列中间隔步长比较
                            {
                                      if(a[k]>a[j])       //寻找它后面的数中最小的数
                                               k=j;       //交换下标,k记录了最小的数的下标
                            }
                            temp=a[k];                    //交换a[i]与a[i]后面最小的数的位置
                            a[k]=a[i];
                            a[i]=temp;       
                   }
 
/*               for(int i=0;i<n;i++)  //这里为了便于理解,打印出了每次for循环后的结果
                   { 
                            cout<<a[i]<<"";
                   }
                   cout<<endl;
*/
 
/*
原序列               43  1  9  54  32  17  88  24  72  48
 
第一次排序:         17  1  9  54  32  43  88  24  72  48        
 
第二次排序:         9      17     32      72      88        --直接插入排序
                        1      24      43      48      54    --直接插入排序
  
第三次排序:         1   9  17 24  32  43  48  54  72  88
*/
         }
        
}
 
void print(int *a, int n)      //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
 
}
int main()
{
         inta[]={43,1,9,54,32,17,88,24,72,48};
 
         print(a,10);
         sort(a,10);
         print(a,10);
 
         return0;
}

3.      冒泡排序

冒泡排序:让较大的数往下沉,较小的往上冒。

#include<iostream>
using namespace std;
void sort(int a[],int n)       //冒泡排序算法
{
         inti,j,temp;          //定义循环变量i,j用于交换的临时变量temp
         for(i=0;i<n;i++)      //依次比较数组中每一个数a[i]
         {
                   for(j=i+1;j<n;j++)//将a[i]后的每一个a[j]与其进行比较
                   {
                            if(a[i]>a[j])     //如果a[j]比a[i]小,交换a[i]与a[j],使a[j]往上冒泡
                            {
                                     temp=a[i];        
                                     a[i]=a[j];
                                     a[j]=temp;
                            }       
                   }
 
/*               for(int i=0;i<n;i++)         //这里为了便于理解,打印出了每次for循环后的结果
                   {
                            cout<<a[i]<<"";
                   }
                   cout<<endl;
*/
         }
}
 
void print(int *a, int n)   //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
 
}
int main()
{
         inta[]={43,1,9,54,32,17,88,24,72,48};
 
         print(a,10);
         sort(a,10);
         print(a,10);
 
         return0;
}

4.      快速排序

快速排序:首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。然后递归调用此函数

#include<iostream>  
using namespace std;  
void print(int *a, int n)   //数组输出函数  
{  
         for(int i=0;i<n;i++)  
         {  
                   cout<<a[i]<<" ";  
         }  
         cout<<endl;  
}

void sort(int a[], int left, int right)
{
    if(left >= right)
    {
        return;
    }
    int i = left;
    int j = right;
    int key = a[i];      /*用第一个记录作为关键字*/

    while(i < j)
    {
        while(i < j && a[j] >= key)   j--;
        a[i] = a[j];          /*将比第一个小的移到低端*/

        while(i < j && a[i] <= key)   i++;
        a[j] = a[i];          /*将比第一个大的移到高端*/

    }

    a[i] = key;               /*关键字记录到位*/
    //print(a,10);  

    sort(a, left, i-1);
    sort(a, i+1, right);
}
    
int main()  
{  
         int a[]={43,1,9,54,32,17,77,24,72,48};  
   
         print(a,10);  
         sort(a,0,9);        //注意:这里参数传递的是数组的下标,所以最大到9  
         print(a,10);  
   
         return 0;  
}  

 

5.      选择排序——简单选择排序

选择排序——简单选择排序:在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换;依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。

#include<iostream>
using namespace std;  
void sort(int a[],int n)                         //简单排序算法
{ 
         inti,j,k,temp;                          //定义循环变量i,j和数组下标变量k以及用于交换的临时变量temp
         for(i=0;i<n-1;i++)                      //依次插入数组中每一个数a[i]
         {
                   k=i;                          //每次开始时,记录下标到k
                   for(j=i+1;j<n;j++)
                   {
                            if(a[k]>a[j])       //寻找它后面的数中最小的数
                                     k=j;       //交换下标,k记录了最小的数的下标
                   }
                   temp=a[k];                   //交换a[i]与a[i]后面最小的数的位置
                   a[k]=a[i];
                   a[i]=temp;
/*     for(int i=0;i<n;i++)                      //这里为了便于理解,打印出了每次for循环后的结果
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
*/              
         }
        
}
 
void print(int *a, int n)   //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
 
}
int main()
{
         inta[]={43,1,9,54,32,17,88,24,72,48};
 
         print(a,10);
         sort(a,10);
         print(a,10);
 
         return0;
}

6.      归并排序

归并排序:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

#include<iostream>
using namespace std;
void print(int *a, int n)     //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
 
}
 
//将a[i…m]和a[m +1 …n]归并到辅助数组b[i…n]
void merge(int *a,int *b, int i, int m, intn) 
{ 
   int j,k; 
   for(k=i,j=m+1; i<=m && j <=n ; k++)
         { 
       if(a[j] < a[i])
                            b[k]= a[j++]; 
       else
                            b[k]= a[i++]; 
    }
        
   //如果a[i…m]和a[m +1 …n]的长度不一样,在上面的for循环中有一个提前终止,则用下面的while循环继续移动
   while(i <= m)  b[k++] =a[i++]; 
   while(j <= n)  b[k++] =a[j++]; 
 
   print(b,n+1);    //代码测试,输出结果
} 
 
void sort(int *a, int *b, int lenght) 
{  
   int len = 1; 
   int *temp ; 
   while(len < lenght)
         { 
       int s = len; 
       len = 2 * s ; 
       int i = 0; 
       while(i+ len <lenght)
                   { 
           merge(a, b,  i, i+ s-1, i+ len-1);  //对等长的两个子表合并 
           i = i+ len; 
       } 
 
                   //按照上面等长合并后,序列最后的几个数可能不能按照等长合并,则将最后几个数和其前面一组等长合并的子序列统一合并
     
           merge(a, b,  i, i+ s-1, lenght-1); //对不等长的两个子表合并,此时合并到了序列最末端 
    
       temp = a;    //交换a,b,以保证下一趟归并时,仍从a归并到b 
                   a= b;
                   b= temp;
 
   } 
} 
 
 
int main()
{
         inta[]={43,1,9,54,32,17,88,24,72,48};
   int b[10]; 
 
         print(a,10);
         sort(a,b,10);
         print(a,10);
 
         return0;
}

7.      基数排序

基数排序:简单来说,就是把数据分组,放在一个个的桶中,然后对每个桶里面的在进行排序。然后收集数据,再放入桶中,循环此操作。

例如,在整理扑克牌顺序时,先按红、黑、方、花的顺序分成4摞(分配),再按此顺序再叠放在一起(收集);然后按面值的顺序分成13摞(分配),再按此顺序叠放在一起(收集),如此进行二次分配和收集即可将扑克牌排列有序。 

#include<iostream>
using namespace std;
void print(int *a, int n)   //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"";
         }
         cout<<endl;
 
}
 
int maxbit(int a[], int n)    //辅助函数,求数据的最大位数,即后面最外层循环的次数
{
   int d = 1;                 //保存最大的位数
   int p = 10;
   for(int i = 0; i < n; ++i)
    {
       while(a[i] >= p)
       {
           p *= 10;
           d++;
       }
    }
   return d;
}
 
void sort(int a[], int n)     //基数排序
{
   int d = maxbit(a, n);
   int *box= new int[n];      //箱子,桶
   int *count = new int[10];  //计数器
   int i, j, k;
   int radix = 1;             //倍率
 
   for(i=0; i<d; i++) //进行d次排序
    {
       for(j = 0; j < 10; j++)     //每次分配前清空计数器
           count[j] = 0;
 
       for(j = 0; j < n; j++)      //统计每个桶中的记录数
       {
           k = (a[j] / radix) % 10;
           count[k]++;
       }
 
for(j = 0; j < 10; j++)            //代码测试,观看每个桶中数的个数count[j]
    cout<< count[j] <<"     ";
cout<<endl;
       
                   for(j= 1; j < 10; j++)      //将box中的位置依次分配给每个桶
           count[j] = count[j - 1] + count[j];
 
for(j = 0; j < 10; j++)                        //代码测试
    cout<< count[j] <<"     ";
cout<<endl;
 
       for(j = n - 1; j >= 0; j--)             //将所有记录依次放到桶中
                   {
           k = (a[j] / radix) % 10;
           box[count[k] - 1] = a[j];
           count[k]--;
       }
 
for(j = 0; j < 10; j++)                        //代码测试
    cout<< box[j] <<"     ";
cout<<endl;
 
       //将已分配好的桶中数据再倒出来(收集数据),此时已是对应当前位数有序的表
       for(j = 0; j < n; j++) //将box复制到a中,为下一次分入不同桶做准备
           a[j] = box[j];
 
       radix = radix * 10;   
                   print(a,10);
    }
   delete[]box;
   delete[]count;
}
 
int main()
{
         inta[]={43,1,9,54,32,17,88,24,72,48};
 
         print(a,10);
         sort(a,10);
         print(a,10);
 
         return0;
}

8.      堆排序

此程序来自百科百度,因为写的相对比较简练,所以拿过来了。

大根堆:所有子节点都小于父节点。

小根堆:所有子节点都大于父节点。

堆排序:将a[n]看作一棵完全二叉树的存储结构,先将a[n]建成一个大堆,此时是无序的,再将a[1]和无序区的最后一个元素a[n]交换,得到新无序区a[1...n-1]和有序区a[n],调整无序区a[1...n-1]为大根队,与无序区的最后一个元素a[n-1]交换;重复上述操作。

#include <iostream>
using namespace std;
//交换函数,参数传入为地址
void swap(int *a,int *b)
{       
         inttemp;
         temp=*a;
         *a=*b;
         *b=temp;
}
 
 
//本函数功能是:根据数组array构建大根堆
void HeapAdjust(int array[],int i,intnLength)     //array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度
{
   int nChild;
   for(;2*i+1<nLength;i=nChild)
    {
       nChild=2*i+1;           //子结点的位置=2*(父结点位置)+1
 
       if(nChild<nLength-1 && array[nChild+1]>array[nChild]) 
             ++nChild;         //得到子结点中较大的结点
 
       if(array[i]<array[nChild])                 //如果子结点大于父结点那么交换子结点和它的父结点
             swap(array[i],array[nChild]);
       else
             break;           //否则退出循环
    }
}
 
 
//堆排序算法
void HeapSort(int array[],int length)
{
   int i;
   for(i=length/2-1;i>=0;--i)         //调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素 length/2-1是最后一个非叶节点,此处"/"为整除
                   HeapAdjust(array,i,length);
   
   for(i=length-1;i>0;--i)            //从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    {
                   swap(array[i],array[0]);        //把第一个元素和当前的最后一个元素交换,
       
       HeapAdjust(array,0,i);         //不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
    }
}
 
 
int main()
{
   int i;
   int num[]={9,3,0,2,5,4,8,6,1,7};
 
   HeapSort(num,sizeof(num)/sizeof(int));
 
   for(i=0;i<sizeof(num)/sizeof(int);i++)
       cout<<num[i]<<"  ";
 
   return 0;
}

9.      二叉树排序

二叉树排序:将一个无序记录插入到建立的二叉树中,二叉树采用左低右高形式,然后用中序遍历二叉树排序。

#include<iostream>
using namespace std;
class node             //树节点类
{
public:
         intdata;          //数据
         node*parent;      //根指针
         node*left;        //左子树指针
         node*right;       //右子树指针
public:
         node(intnum):data(num),parent(NULL),left(NULL),right(NULL) {};     //构造函数,初始化数据成员
 
};
 
class tree            //树类
{
public:
         tree(intnum[],int len);                      //构造函数
         voidinsertNode(int data);                   //插入结点
         voidinOrderTree();                           //中序遍历
 
private:
         voidinsertNode(node *current,int data);     //插入结点的递归函数
         voidinOrderTree(node *current);             //中序遍历递归函数
 
         node*root;                                  //树根
};
 
tree::tree(int num[],int len)                   
{
         root=newnode(num[0]);              //构造函数中初始化树根
         for(int i=1;i<len;i++)              //循环插入树节点
                   insertNode(num[i]);
}
 
void tree::insertNode(int data)         //插入结点时,调用私有的插入函数
{
         if(root!=NULL)
                   insertNode(root,data);        
}
void tree::insertNode(node *current,intdata)
{
         if(data< current->data)
         {
                   if(current->left==    NULL)
                   {
                            current->left=new node(data);
                            current->left->parent=current;
                   }
                   else
                            insertNode(current->left,data);
        
         }
 
         elseif(data > current->data)
         {       
                   if(current->right== NULL)
                   {
                            current->right=new node(data);
                            current->right->parent=current;
                   }
                   else
                            insertNode(current->right,data);
        
         }
         return;
 
}
 
 
void tree::inOrderTree()     //中序遍历,调用私有中序遍历函数
{
         if(root==NULL)
                   return;
         inOrderTree(root);
 
}
void tree::inOrderTree(node *current)
{
         if(current!=NULL)
         {
                   inOrderTree(current->left);
                   cout<<current->data<<"  ";
                   inOrderTree(current->right);
         }
}
 
 
int main()
{
         inta[8]={5,3,7,2,4,6,8,1};
         treet(a,8);          //利用构造函数建立树
         t.inOrderTree();      //中序遍历
         return0;
}

10. 顺序查找

顺序查找(简单查找):在一组无序数列中,查找特定某个数值,并返回其位置pos。

#include<iostream>
using namespace std;
#define MAX 20              //定义数组元素的个数
void randarray(int num[])   //随机产生数组元素并输出
{ 
   for(int i=0; i<MAX; i++) 
       cout<<(num[i]=rand()%100)<<"  "; 
} 
 
int find(int num[], int x)  //从数组开头依次查找,如果找到返回查找到的位置
{ 
   for(int i=0; i<MAX; i++) 
       if(x == num[i]) 
           return i; 
   return 0; 
} 
 
void main() 
{ 
   int x, pos, num[MAX]; 
   randarray(num); 
    
         cout<<endl<<"Enterfind num: ";
     
         cin>>x;
 
   pos=find(num, x);
 
   if(pos) 
      cout<<"OK! "<<x<<" is found in pos:"<<pos<<endl; 
   else 
            cout<<"Sorry!  "<<x<<" is not found inthe array"<<endl; 
 
} 

11. 折半查找

折半查找(二分查找):二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x。

#include<iostream>
using namespace std;
#define MAX 10                  //定义数组元素的个数
void randarray(int a[],int n)   //随机产生数组元素并输出
{ 
   for(int i=0; i<n; i++) 
       a[i]=rand()%100;
} 
 
void print(int a[], int n)      //数组输出函数
{
         for(int i=0;i<n;i++)
         {
                   cout<<a[i]<<"  ";
         }
         cout<<endl;
}
 
void sort(int a[], int low, int high)   //快速排序算法
{
         int i,j,pos;
         if(low< high)
         {
                   pos=a[low];
                   i=low;
                   j=high;
                   while(i<j)
                   {
                            while(i<j&& a[j]>pos)  j--;   //查找比pos小的数a[j],往后放
                                a[i]=a[j];
                                                            
                            while(i<j&& a[i]<pos)  i++;    //查找比pos大的数a[i],往前放
                                a[j]=a[i];
                   }
                   a[i]=pos;
                   sort(a,low,i-1);       //注意,这里是i-1
                   sort(a,i+1,high);
 
         }
 
}
 
int find(int a[], int n,int x)     //二分查找,如果找到返回查找到的位置
{
   int low=0,high=n;
   int mid;
         while(low<=high)
         {
                   mid=(low+high)/2;
                   if(a[mid]>x)
                         high=mid-1;
                   else if(a[mid]<x)
                         low=mid+1;
                   else 
	           {
			  return mid;   //这里有一个bug,如果找的数位于a[0],则找到后,mid=0,return 0后会返回没找到的假象
		          break;
	  <span style="white-space:pre">	</span>   }
		
         }
   return 0; 
} 
 
void main() 
{ 
   int x, pos, a[MAX]; 
 
   randarray(a,MAX); 
   print(a,MAX);
 
   sort(a,0,MAX-1);
   print(a,MAX);
        
   cout<<endl<<"Enterfind num: ";
   cin>>x;
 
   pos=find(a,MAX, x);
 
   if(pos) 
      cout<<"OK! "<<x<<" is found in pos after sorted: "<<pos<<endl; 
   else 
      cout<<"Sorry!  "<<x<<" is not found inthe array"<<endl; 
 
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值