C++实现常见排序算法

  1. 本程序参考了网上各位大牛和数据结构中的程序,VS2005运行通过,如有问题,请各位大牛指正。

    实现的排序有:直接插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序等等


  2. #include <iostream>  
  3. using namespace std;  
  4. const int len = 100;  
  5. class CSort  
  6. {  
  7. public:  
  8.     CSort();  
  9.     ~CSort();  
  10.     virtual void sort()=0;  
  11.     void swap(int& a,int& b);  
  12.     friend ostream& operator<<(ostream &cout,const CSort& csort);  
  13. protected:  
  14.     int* arr;  
  15.     int length;  
  16. };  
  17.   
  18. CSort::CSort():length(len)  
  19. {  
  20.     arr = new int[length];  
  21.     for (int i=0;i<length;i++)  
  22.     {  
  23.         arr[i]=rand()%1000;  
  24.     }  
  25. }  
  26.   
  27. CSort::~CSort()  
  28. {  
  29.     delete[]arr;  
  30. }  
  31.   
  32. void CSort::swap(int& a,int& b)  
  33. {  
  34.     int temp = a;  
  35.     a=b;  
  36.     b=temp;  
  37. }  
  38.   
  39. ostream& operator<<(ostream& cout,const CSort& csort)  
  40. {  
  41.     for (int i=0;i<csort.length;i++)  
  42.     {  
  43.         cout<<csort.arr[i]<<" ";  
  44.     }  
  45.     cout<<endl;  
  46.     return cout;  
  47. }  
  48. /* 
  49. 插入排序思想:将一个记录插入到已经排好的有序表中,从而得到一个新的、记录增1的有序表,直到将所有待排记录全部插入为止 
  50. */  
  51.   
  52. class CInsertSort : public CSort  
  53. {  
  54. public:  
  55.     void sort();  
  56. };  
  57.   
  58. //直接插入排序--小 到 大  
  59. void CInsertSort::sort()  
  60. {  
  61.     int i,j;  
  62.     int key;//存放乱序的元素  
  63.     for ( i=1;i<length;i++)  
  64.     {  
  65.         if (arr[i-1]>arr[i])  
  66.         {  
  67.             key=arr[i];  
  68.             for ( j=i-1;j>=0 && arr[j]>key;j--)  
  69.             {  
  70.                 arr[j+1]=arr[j];                  
  71.             }  
  72.             arr[j+1]=key;  
  73.         }  
  74.     }  
  75. }  
  76.   
  77. class BInsertSort : public CSort  
  78. {  
  79. public:  
  80.     void sort();  
  81.   
  82. };  
  83. void BInsertSort::sort()  
  84. {  
  85.     for (int i=1;i<length;i++)  
  86.     {  
  87.         //先找到要插入的位置  
  88.         int low = 0;  
  89.         int high = i-1;  
  90.         while(high>=low)  
  91.         {  
  92.             int mid = (low+high)/2;  
  93.             if (arr[i]>arr[mid])  
  94.             {  
  95.                 low=mid+1;  
  96.             }  
  97.             else  
  98.             {  
  99.                 high=mid-1;  
  100.             }  
  101.         }  
  102.         //找到应该插入的位置high+1,之后移位置  
  103.         int key = arr[i];  
  104.         for (int j=i-1;j>=high+1;j--)  
  105.         {  
  106.             arr[j+1]=arr[j];  
  107.         }  
  108.         //已经找到位置,把要排序的数放入其中  
  109.         arr[high+1]=key;  
  110.     }  
  111. }  
  112.   
  113. class CShellInsert : public CSort  
  114. {  
  115. public:  
  116.     void sort();  
  117. private:  
  118.     void ShellInsert(int dk);  
  119. };  
  120.   
  121. void CShellInsert::sort()//调用希尔排序  
  122. {  
  123.     int dlta[3]={5,3,1};//设置希尔排序的增量,调用希尔排序函数  
  124.     for (int i=0;i<3;i++)  
  125.     {  
  126.         ShellInsert(dlta[i]);  
  127.     }  
  128. }  
  129.   
  130. void CShellInsert::ShellInsert(int dk)//希尔排序函数,把直接插入排序中的1变成dk就好,直接插入排序中增量为1  
  131. {  
  132.     int i,j;  
  133.     int key;//存放乱序的元素  
  134.     for (i=dk;i<length;i++)  
  135.     {  
  136.         if (arr[i-dk]>arr[i])  
  137.         {  
  138.             key=arr[i];  
  139.             for (j=i-dk;j>=0 && arr[j]>key;j=j-dk)  
  140.             {  
  141.                 arr[j+dk]=arr[j];                 
  142.             }  
  143.             arr[j+dk]=key;  
  144.         }  
  145.     }  
  146. }  
  147.   
  148. /*气泡排序*/  
  149. class BubbleSort:public CSort  
  150. {  
  151. public:  
  152.     void sort();  
  153. };  
  154.   
  155. void BubbleSort::sort()  
  156. {  
  157.     bool change = true;//表示第i个位置的元素在确定位置时,是不是有换位置。true表示,下面的数据还没拍好。没有的话,说明下面元素已经排好,不用在继续下去  
  158.     for (int i=0;i<length-1 && change;i++)   
  159.     {  
  160.         change = false;//先设置已经拍好  
  161.         for (int j=0;j<length-1-i;j++)  
  162.         {  
  163.             if (arr[j]>arr[j+1])  
  164.             {  
  165.                 change = true;//需要调换位置  
  166.                 swap(arr[j],arr[j+1]);  
  167.             }  
  168.         }  
  169.     }  
  170. }  
  171.   
  172. /*快速排序*/  
  173. class CQuickSort:public CSort  
  174. {  
  175. public:  
  176.     void sort();  
  177. private:  
  178.     int Partition(int low,int high);  
  179.     void QuickSort(int low,int high);  
  180. };  
  181.   
  182. void CQuickSort::sort()  
  183. {  
  184.     QuickSort(0,len-1);  
  185. }  
  186.   
  187. int CQuickSort::Partition(int low,int high)  
  188. {  
  189.     int key=arr[low];//先挖第一个洞  
  190.     while(low<high)  
  191.     {  
  192.         while(low<high && arr[high]>=key)//此时,low位置待放元素:比较时,比枢轴元素大,位置不变  
  193.             high--;  
  194.         arr[low]=arr[high];//见到第一个比枢轴元素小的,应该把这个元素放到洞(左边)中。  
  195.         while(low<high && arr[low]<=key)//这时,应该从另一侧进行检测,high待放元素,比较时,比枢轴元素小,位置不变  
  196.             low++;  
  197.         arr[high] = arr[low];//见到第一个比枢轴元素大的,应该把这个元素放到洞中(右边)  
  198.     }  
  199.     arr[low]=key;//这时第一个洞的元素应该是在low处  
  200.     return low;//返回这次划分的位置  
  201. }  
  202.   
  203. void CQuickSort::QuickSort(int low,int high)  
  204. {  
  205.     if (low<high)  
  206.     {  
  207.         int keyloc = Partition(low,high);//在keyloc的元素已经找到正确的位置了  
  208.         QuickSort(low,keyloc-1);//分别对之后低子表进行快排  
  209.         QuickSort(keyloc+1,high);//分别对之后高子表进行快排  
  210.     }  
  211. }  
  212.   
  213. class CSelectionSort:public CSort  
  214. {  
  215. public:  
  216.     void sort();  
  217. };  
  218.   
  219.   
  220. void CSelectionSort::sort()  
  221. {  
  222.     for (int i=0;i<length-1;i++)  
  223.     {  
  224.         int k = i;  
  225.         for (int j=i+1;j<length;j++)  
  226.         {  
  227.             if (arr[j]<arr[k])//要求的序列是由小到大,这里k应该记得是小值,if条件成立时,记的就为大值  
  228.             {  
  229.                 k=j;  
  230.             }  
  231.         }  
  232.         if (k!=i)  
  233.         {  
  234.             swap(arr[i],arr[k]);  
  235.         }  
  236.     }  
  237. }  
  238.   
  239. class CHeapSort:public CSort  
  240. {  
  241. public:  
  242.     void sort();  
  243. private:  
  244.     void HeapSort();  
  245.     void HeapAdjust(int s,int m);  
  246. };  
  247.   
  248. void CHeapSort::sort()  
  249. {  
  250.     HeapSort();  
  251. }  
  252.   
  253. /* 
  254. 堆排序: 
  255. 初始数据:存储在数组arr中 
  256. 建立初始堆排序时, 
  257. 首先把无序序列看成一个完全二叉树:处在0号元素的为根,12号为左右子树之后一次化成完全二叉树的形式画树 
  258. 调整初始堆时,应该从最后一个非叶子节点开始调整 
  259. 在建立初始堆后,再进行调整堆,输出序列 
  260. 首先是堆顶元素(总是数组的第一个元素)和最后一个未排好的元素交换(一直在变化),之后进行调整堆就好 
  261. 调整堆时,总是自上而下的调整。即使是在建堆的时候也是这样的。 
  262. 注意:建初始堆和排序时的调整堆都需调用调堆函数HeapAdjust,两种的不同之处在于调换元素和顺序不同 
  263. */  
  264. void CHeapSort::HeapSort()//堆排序  
  265. {  
  266.     for (int i=length/2-1;i>=0;i--)//建堆,相当于从序号m-0的非叶子结点开始调整  
  267.     {  
  268.         HeapAdjust(i,length);  
  269.     }  
  270.     for (int j=length-1;j>0;j--)  
  271.     {  
  272.         swap(arr[0],arr[j]);//调整堆后,第一个元素总是存放着最大的元素(由小到大排序的),让其给最后一个元素j交换  
  273.         HeapAdjust(0,j);  
  274.     }  
  275. }  
  276.   
  277. //要从小到大排序:建立大根堆,把顶端元素(数组中第一个元素)和数组中 最后一个未排 元素交换  
  278.   
  279. //s表示调换的位置,m表示未排好序列的个数  
  280. void CHeapSort::HeapAdjust(int s,int m)//调整推,变成大根堆  
  281. {  
  282.     int key =arr[s];//先把要调整的元素取出来,传过来的  
  283.     //之后对非终结点进行调整  
  284.     for (int i=2*s+1;i<m;i=2*i+1)  
  285.     {  
  286.         if (i<m-1 && arr[i] < arr[i+1])//先让要调整元素的两个孩子进行调整,其中i下标保存最大的值 i<m-1:保证其有左右孩子时,才进行左右孩子的比较  
  287.         {  
  288.             i++;  
  289.         }  
  290.         if (key > arr[i])//这时,根保存着最大值,不用调整(建立大根堆)  
  291.         {  
  292.             break;  
  293.         }  
  294.         arr[s]=arr[i];  
  295.         s=i;//这时,s应该指向刚刚调过去的位置,因为,在调整时,总是从上而下进行的,要从他的左孩子开始  
  296.     }  
  297.     arr[s]=key;  
  298. }  
  299.   
  300. /*归并排序*/  
  301. class CMergingSort:public CSort  
  302. {  
  303. public:  
  304.     void sort();  
  305. private:  
  306.     void MergeSort(int left,int right);  
  307.     void Merge(int left,int mid,int right);  
  308. };  
  309. void CMergingSort::sort()  
  310. {  
  311.     MergeSort(0,length-1);  
  312. }  
  313.   
  314. void CMergingSort::MergeSort(int left,int right)  
  315. {  
  316.     if (left<right)  
  317.     {  
  318.         int mid = (left+right)/2;  
  319.         MergeSort(left,mid);  
  320.         MergeSort(mid+1,right);  
  321.         Merge(left,mid,right);        
  322.     }  
  323. }  
  324.   
  325. void CMergingSort::Merge(int left,int mid,int right)  
  326. {  
  327.     int* temp = new int[right - left + 1];  
  328.     int i=left;  
  329.     int j=mid+1;  
  330.     int k=0;  
  331.     while(i<=mid && j<=right)  
  332.     {  
  333.         if (arr[i]>arr[j])  
  334.         {  
  335.             temp[k++]=arr[j++];  
  336.         }  
  337.         else  
  338.         {  
  339.             temp[k++]=arr[i++];  
  340.         }  
  341.     }  
  342.     while(i<=mid)  
  343.     {  
  344.         temp[k++]=arr[i++];  
  345.     }  
  346.     while(j<=right)  
  347.     {  
  348.         temp[k++]=arr[j++];  
  349.     }  
  350.     for (i=0,k=left;k<=right;k++,i++)//归并后的数组对应的原来的数组是 left--right 那段,因此还要把这段数据放到原数组中  
  351.     {  
  352.         arr[k]=temp[i];  
  353.     }  
  354.     delete []temp;  
  355. }  
  356.   
  357. int main()  
  358. {  
  359.     CSort *pCsort;//执行这条代码时,是不调用类CSort的构造函数的  
  360.     //pCsort = new CInsertSort();//直接插入排序  
  361.     //pCsort = new BInsertSort();//测试折半插入  
  362.     //pCsort = new CShellInsert();//测试希尔排序  
  363.     //pCsort = new BubbleSort();//冒泡排序  
  364.     //pCsort = new CQuickSort();//快速排序  
  365.     //pCsort = new CSelectionSort();//选择排序  
  366.     pCsort = new CMergingSort();//堆排序  
  367.       
  368.     cout<<"排序前:"<<endl;  
  369.     cout<<*pCsort<<endl;  
  370.   
  371.     pCsort->sort();//排序  
  372.   
  373.     cout<<"排序后:"<<endl;  
  374.     cout<<*pCsort<<endl;  
  375.   
  376.     //pCsort = new CMergingSort();//归并排序  
  377.     system("pause");  
  378.     return 1;  
  379. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值