排序算法笔记

注:部分代码来自网上

冒泡排序:
相临数据不停交换,这样每一趟后,后面一个数据就是最大或者最小的了。
可以采取保存最后一次交换的位置来减少交换次数,因为这代表此位置后面数据没有发生交换,已经有序列了。
此算法缺点是交换的次数过多
//冒泡排序3
void BubbleSort3(int a[], int n)
{
    int j, k;
    int flag;

    flag = n;
    while (flag > 0)
    {
        k = flag;
        flag = 0;
        for (j = 1; j < k; j++)//K后面已经有序
            if (a[j - 1] > a[j])//相临的交换
            {
                Swap(a[j - 1], a[j]);
                flag = j;//发生交换的最后点
            }
    }
}

选择排序:
每趟找一个最大或者最小的,交换到开关,比较次数同冒泡算法差不多,但交换每遍只进行一次,算法复杂度都是O(n*n),但执行操作少一点,速度理论上快些
void Selectsort(int a[], int n)
{
int i, j, nMinIndex;
for (i = 0; i < n; i++)
{
nMinIndex = i; //找最小元素的位置
for (j = i + 1; j < n; j++)
if (a[j] < a[nMinIndex])
nMinIndex = j;


Swap(a[i], a[nMinIndex]); //将这个元素放到无序区的开头
}
}

快速排序:
分治思想,每次找到一个“基准数”,把大于此数的放在右边,小于此数的放在左边。然后分成了左右两边,再把左右两边分别进行前面的操作,直到无法再分为止,
具体实施的时候,过程类似数列左右两边开始找数,左边找大于基数的,右边找小于基数的,然后互相交换位置。依此类推。
如果遇到倒序或者全部相等就惨了,需要进行优化。
//快速排序
void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
        //if(r -l < 16){//当数据量较小时候,再进行分组快排,分组次数较多,不划算,可以采用短数量排序的优势排序方法:插入排序
        //    进行插入排序//-----------------------------也是优化办法之一
        }
        //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换
        //基数X 可以取left   mid   right  或者三者中大小处于中间的数,或者随机一个位置等
        int i = l, j = r, x = s[l];
        while (i < j)
        {
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数, 此时真要判断等于?这样如果遇到等于也进行跳过,如果全部等于时候,划分的话就应该会划分成1:[n -1],那样每次只划分出一个元素。
//如果不加等于判断,那相等的元素会每次划分进入下一次的递归排序过程,左右各一半。其实跟基数X相等的元素可以不排序了
//那样就有了另外一种优化,每次递归分三段,中间一段是全部相等的X,不再进行排序
//但感觉有一定优化性,特别相等的很多时候,但同时需要交换保存相等的元素到中间,也有消耗,优化的应该有限。
                j--;
            if(i < j)
                s[i++] = s[j];//A

            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
                i++;
            if(i < j)
                s[j--] = s[i];//与A处一起,完成一次交换
        }
        s[i] = x;//左右已经分两边了,空出了中间位置,给基数用。
        quick_sort(s, l, i - 1); // 递归调用
        quick_sort(s, i + 1, r);
    }
}



插入排序
从左边开始,认为左边有序,然后把右边数一个一个插入到左边去。
具体实施过程可能是左边的有序数列,从有序数列右边开始,一个一个的向右移动一位,直到移出到新要插入的那个数值的位置为止,然后插入它。
//插入排序
void Insertsort2(int a[], int n)
{
    int i, j;
    for (i = 1; i < n; i++)
        if (a[i] < a[i - 1])//i是右边要插入到左边的数,如果已经是大的,也就是代表有序了。跳过。
        {
            int temp = a[i];//
            for (j = i - 1; j >= 0 && a[j] > temp; j--)//开始与要插入的数进行比较移位,直到移出合适位置
                a[j + 1] = a[j];
    //OK
            a[j + 1] = temp;
        }
}


希尔排序
插入排序的一种优化,插入排序每趟最大的消耗在于要移动出新插入数据的空位,随着有序的数据长的时候,移动的次数可能很多。如果进行分组,每一组数据量并不大,这样少量数据的插入排序,消耗就会小很多。
希尔排序就是基于分组思想,但分组并非连续的分组,而是把相隔固定值的全部数据分为一组。而这个间隔值会慢慢的变小,直到间隔只有一个,也就是完全分为一组了,进行最后的一次插入排序。
其优化在于小组内快排较快,后面分组时候间隔较小,分组的元素会变多,但由于之前分组进行过大概的排序,已经基本有序,所以后面的插入排序会较快。
void shellsort2(int a[], int n)
{
int j, gap;

for (gap = n / 2; gap > 0; gap /= 2)//固定间隔值步步移到1
for (j = gap; j < n; j++)//从数组第gap个元素开始
if (a[j] < a[j - gap])//每个元素与自己组内的数据进行直接插入排序
{
int temp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > temp)
{
a[k + gap] = a[k];
k -= gap;
}
//找到位置,插入之
a[k + gap] = temp;
}
}

归并排序:
也是分治办法 由于要归并两个有序列的  需要分配中间缓存数组
//将有二个有序数列a[first...mid]和a[mid...last]合并。
void mergearray(int a[], int first, int mid, int last, int temp[])
{
    int i = first, j = mid + 1;
    int m = mid,   n = last;
    int k = 0;

    while (i <= m && j <= n)
    {
        if (a[i] <= a[j])
            temp[k++] = a[i++];
        else
            temp[k++] = a[j++];
    }

    while (i <= m)
        temp[k++] = a[i++];

    while (j <= n)
        temp[k++] = a[j++];

    for (i = 0; i < k; i++)//归并完后,数据回归到a[]
        a[first + i] = temp[i];
}
void mergesort(int a[], int first, int last, int temp[])
{
    if (first < last)
    {
        int mid = (first + last) / 2;
        mergesort(a, first, mid, temp);    //左边有序
        mergesort(a, mid + 1, last, temp); //右边有序
        mergearray(a, first, mid, last, temp); //再将二个有序数列合并
    }
}

bool MergeSort(int a[], int n)
{
    int *p = new int[n];
    if (p == NULL)
        return false;
    mergesort(a, 0, n - 1, p);
    delete[] p;
    return true;
}


堆排序:
堆的定义具体网上有,大概是个完全二叉树,然后根节点都大于或者小于叶子节点。
一,数据保存采用线性保存办法,所以取左右子节点时候需要index*2 + 1跳着移动。
二,建立堆,需要直观的表达是从金字塔的倒数第二排开始,一层层的向上走,比较移动后,保存每个节点的左右子节点有大于或者小于它的性质。
三,建立后,堆本身最上面的一个塔尖数是最大或者最小的数了,把它移到最后节点n-1.封存T除掉。同时把a[n-1]放截尖。
四,此时堆又不对了,需要进行调整,需要再次把塔尖的数进行下沉操作。
下沉操作:把塔尖的数据下向移动,直到发现父母节点比子节点都小,代表OK了。
有个特性是,由于下沉过程中,只移动了数据有才进行递归移动,其它分支没有移动的,并没有改变它们的性质。

void HeapSort(int num[] ,int size)
21 {
22     int i;
23     int iLength=size;
24      
25     PrintHeap("Befor Sort:",num,iLength);
26      
27     BuildHeap(num,size);// 建立小顶堆  
28      
29     for (i = iLength - 1; i >= 1; i--) {  
30         Swap(num, 0, i);// 交换  
31         size--;// 每交换一次让规模减少一次  
32         PercolateDown(num, 0,size);// 将新的首元素下滤操作
33         PrintHeap("Sort Heap:",num,iLength); 
34     }
35 }
36  
37 // 建堆方法,只需线性时间建好  
38 void BuildHeap(int num[] ,int size) {
39     int i;
40     for (i = size / 2 - 1; i >= 0; i--) {// 对前一半的节点(解释为“从最后一个非叶子节点开始,将每个父节点都调整为最小堆”更合理一些)  
41         PercolateDown(num, i,size);// 进行下滤操作
42         PrintHeap("Build heap:",num,size);
43     }  
44 }
45      
46 // 对该数进行下滤操作,直到该数比左右节点都小就停止下滤  
47 void PercolateDown(int num[] , int index,int size) {  
48     int min;// 设置最小指向下标  
49     while (index * 2 + 1<size) {// 如果该数有左节点,则假设左节点最小  
50         min = index * 2 + 1;// 获取左节点的下标  
51         if (index * 2 + 2<size) {// 如果该数还有右节点  
52             if (num[min] > num[index * 2 + 2]) {// 就和左节点分出最小者  
53                 min = index * 2 + 2;// 此时右节点更小,则更新min的指向下标  
54             }  
55         }  
56         // 此时进行该数和最小者进行比较,  
57         if (num[index] < num[min]) {// 如果index最小,  
58             break;// 停止下滤操作  
59         else {  
60             Swap(num, index, min);// 交换两个数,让大数往下沉  
========================================只是因为此时进行了交换,所以才发现其叶子节点的树,特性发生了改变,update index为min.叶子节点.
61             index = min;// 更新index的指向  
62         }  
63     }// while  
64 }







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值