排序用到的数据结构 (1)线性表 (2)数组元素交换操作 ```c #include <stdio.h> #define MAXSIZE 10 typedef struct{ int r[MAXSIZE+1] ; // r[0]用于存储哨兵或临时变量 int length; }SqList;
void swap(SqList l,int i,int j){ int temp = l->r[i]; l -> r[i] = l->r[j]; l->r[j] = temp; }(3)数组打印c void printSqlList(SqList l){ for (int i = 0; i < l-> length+1; i++) { printf("%d , ",l-> r[i]); } } ```
算法实现: (1)冒泡排序每次循环都把一个最小的元素放到无序表的最顶端 (2)这个比较要从线性表的最后一位开始,逐个比较,把小的交换到前面,不断比较到线性表的开头,此时,最小的元素被放到了最开始的位置。 (3)当发现某一次循环中,未发生元素交换,就是说每个相邻元素,都是左小右大的,此时,线性表已经全具有序,不需要再次比较。引入flag比较为
/* 冒泡排序 */ void bubbleSort(SqList *list){ int flag = 1; for (int i = 1; i < list->length && flag ; i++) { // 数组0位置不是元素 flag = 0; for (int j = list->length-1; j >= i; j--) { if(list->r[j+1] < list->r[j]){ flag = 1; // 产生交换操作,下一次还需要进行比较交换 swap(list,j,j+1); } } } }(4)冒泡排序的时间复杂度 最好情况:线性表已经有序,需要比较n-1次 最坏情况:比较次数(n-1) + (n-2) + (n-3)+ ... +3 + 2 + 1 = \(\frac{n(n-1)}{2}\) 所以总时间复杂度:O(n^2)
简单选择排序的时间复杂度 所有的比较次数:最后一趟比较1次,倒数第二趟比较2次,所以一共比较1+2+3+..+(n-1)=\(\frac{n(n-1)}{2}\) 最好的时候,交换次数为0,最坏的情况下,交换次数为O(n),所以比较次数+交换次数形成算法的时间复杂度O(\(n^2\)),
/* 简单选择排序 */ void simpleSelest(SqList *list){ for (int i = 1; i < list->length; i++) { for (int j = i+1; j <= list->length; j++) { int min = i; if(list->r[min]>list->r[j]) min = j; if(min != i) swap(list,i,min); } } }算法
/* 直接插入排序 */ void insertSort(SqList *list){ for (int i = 2; i <= list->length ; i++) { // 初始情况下,认为第一个数据是有序列表 if(list->r[i] < list->r[i-1]){ list->r[0] = list->r[i]; // 哨兵 int j; for (j = i-1; list->r[j] > list->r[0] ; j--) { // 从插入元素向前查,找到需要插入的位置 list->r[j+1] = list->r[j]; } list->r[j+1] = list->r[0]; } printSqlList(list); printf("\n"); } }希尔排序的思想: 希尔排序是分组内的直接插入排序。每趟保证分组内有序,最后increment为1,进行一次全部的直接插入排序
/* 希尔排序 */ void shellSort(SqList *list){ int increament = list->length ; do{ increament = increament/3 + 1; // 增量序列 printf("increament is %d :",increament); for (int i = increament+1; i <= list->length ; i++) { if(list->r[i] < list->r[i-increament]){ // 初始时r[1]与r[increment]比较 list->r[0] = list->r[i]; // 暂存 int j = 0; // 下面的形式就是直接插入排序的代码,但是希尔时分组的,所以比较后的移位移动increment位 for (j = i-increament; j>0 && list->r[0] < list->r[j] ; j-=increament) { list->r[j+increament] = list->r[j]; } list->r[j+increament] = list->r[0]; } } printSqlList(list); }while (increament > 1); }概念 (1)堆排序是对简单选择排序的一种改进,简单选择排序在待排序的n个记录中选择一个最小记录需要比较n-1次。可是这种操作没有把每一趟的比较结果保存。而堆排序,改进了这种情况 (2)节点大于等于左右孩子结点的完全二叉树称为大顶堆 节点小于等于左右孩子节点的完全二叉树称为小顶堆
堆排序的思想: (1)将待排序的序列形成大顶堆,使得根节点为待排数中最大的数 (2)将这个堆顶根节点和堆数组末尾的元素交换,使得堆数组的末尾元素为最大值,然后再将前面的n-1个结点序列重新构成一个堆,这样就能得到次小值。如此反复,得到一个有序序列。 ```c #include <stdio.h> #define MAXSIZE 20 typedef int ElementType; typedef struct { // 定义线性表 ElementType Data[MAXSIZE]; int length; }SqList;
int getElem(SqList list,int i,ElementType e){ if(list.length ==0 || i <1 || i>list.length) return 0;e = list.Data[i]; return 1; // 1代表成功 }
int insertList(SqList *list,int i, ElementType e){ if (list->length == MAXSIZE || i<1 || i>list->length+1 ) return 0; // 插入数据时将被查位置后的元素向后移1位,如果是在最后一位操作,则不用这个操作 if(i <= list->length){ for(int j=list->length-1;j>i-1;j--){ list->Data[j+1] = list->Data[j]; } } list->Data[i-1] = e; // 线性表角标=数组角标+1 list->length++; return 0; }
void HeapAdjust(SqList list,int s,int m){ int temp ; temp = list->Data[s]; printf("tmp is : %d\n",temp); for (int i = 2s; i <= m ; i = 2) { if(i<m && list->Data[i]Data[i+1]) ++i; // i是关键字中较大的记录下标 if(temp >= list->Data[i]) break; list->Data[s] = list->Data[i]; s = i; } list->Data[s] = temp; } / 堆排序 / void heapSort(SqList list){ int i; for (int i = list->length/2; i > 0 ; i--) { HeapAdjust(list,i,list->length); } for (int i = list->length; i > 1 ; i--) { int temp = list->Data[i]; list->Data[i] = list->Data1; list->Data1 = temp; HeapAdjust(list,1,i-1); } }
int main(){ printf("start\n"); SqList list = {{999,13,25,3,99,41},5}; SqList *l = &list; heapSort(l); for (int i = 0; i < 6; ++i) { printf( "%d, ",list.Data[i]); } } ```
代码实现
#define MAXSIZE 10 typedef struct{ int r[MAXSIZE+1] ; // r[0]用于存储哨兵或临时变量 int length; }SqList; void qsort(SqList *L,int low ,int high); int partition(SqList *L,int low,int high); void quickSort(SqList *L){ qsort(L,1,L->length); } void qsort(SqList *L,int low ,int high){ /* 递归调用,对枢轴左边和右边分别递归 */ int pivot; /* 枢轴 */ if(low < high){ pivot = partition(L,low,high); /* 调整枢轴到正确的位置 */ qsort(L,low,pivot-1); qsort(L,pivot+1,high); } } int partition(SqList *L,int low,int high){ printf("low:%d,high:%d\n",low,high); int pivotkey; pivotkey = L->r[low]; while(low<high){ while(low<high && L->r[high] >= pivotkey) /* 找到右侧比pivot数小的 */ high--; swap(L,low,high); while(low<high && L->r[low] <= pivotkey) /* 找到左侧比pivot数大的 */ low++; swap(L,low,high); } return low; /* 跳出while时,low=high=枢轴位置 */ } /********* 测试代码 *********/ int main(){ SqList list = {{-100,13,25,3,12,8,67,99,41,33,24},10}; SqList *l = &list; quickSort(l); for (int i = 1; i < 10; ++i) { printf( "%d, ",list.r[i]); } }转载于:https://www.cnblogs.com/moonlord/p/5938064.html