排序难点:算法多,容易混淆
1.直接(简单)插入排序:扑克牌特点:越有序越快,完全有序O(n),非常重要,这个是希尔排序的基础
2.希尔(shell)排序
分组后利用直接插入排序
3.冒泡排序:
两两比较,大的往后走* 4.快速排序:
算法: 1.从后往前找比基准小的数字,找到往前挪
2.从前往后找比基准大的数字,找到往后挪
3.重复1.2
缺点:1.越有序,越慢
2.空间复杂度大,不稳定5.选择排序:
每次都从待排序中选出最小的一个和待排序的第一个进行数据交换6.堆排序:
算法:1.从最后一颗子树开始,从后往前调整
2.每次调整,从上往下调整
3.调整为大根堆
大根堆:在二叉树中所有的父都大于子
小根堆:在二叉树中所有的父都小于子
度:就是节点的分支
叶子节点:度为0
兄弟:同一个双亲的孩子之前被称为兄弟
深度:就是树的层高7.归并排序
1.将两段有序的数据合并成为一段有序的数据,直到所有的数据都有序
2.把两段有序的归并成为一段有序的,也称为2路有序
8.基数排序(桶排序)
局限性:不能处理负数
9.第‘9’个排序
链表排序
1.单链表存放数据我们用什么排序?(冒泡,选择)
2.双向链表存放数据我们用什么排序?(快排(STL自带的list为双向链表))
#include <stdio.h> #include<stdlib.h> #include<assert.h> #include"listqueue.h" //直接(简单)插入排序 //void InsertSort(int* arr, int len)//O(n^2),最好的情况,O(1),稳定 //{ // int tmp;//存放当前处理的数字 // int j; // for (int i = 1; i < len; i++)//从第二个数字开始 // {//1 2 3 4 5 // tmp = arr[i]; // for (j = i - 1; j >= 0; j--)//从后往前找第一个比tmp小的数字 // { // if (arr[j] > tmp)//arr[j]需要后移 // arr[j + 1] = arr[j]; // else // break; // } // arr[j + 1] = tmp; // } //} //gap:分组数 //void Shell(int* arr, int len, int gap) //{ // int tmp;//保存当前需要处理的值 // int j; // for (int i = gap; i < len; i++)//从"第二个"元素开始 // { // tmp = arr[i]; // for (j = i - gap; j >= 0; j -= gap) // { // if (arr[j] > tmp) // arr[j + gap] = arr[j]; // else // break; // } // arr[j + gap] = tmp; // } //} //希尔排序 //void ShellSort(int* arr, int len)//时间复杂度:O(n^1.3~n^1.5),空间复杂度O(1),不稳定 //{ // int d[] = { 5,3,1 };//分组组数,注意最后一定是1.缩小增量 // for (int i = 0; i < sizeof(d) / sizeof(d[0]); i++) // { // Shell(arr, len, d[i]); // } //} /* void InsertSort(int* arr, int len)//O(n^2),完全有序O(n^2)这个程序写的有问题 { int tmp; int i; int j; for (i = 1; i < len; i++)//从第二个数字开始处理 { tmp = arr[i];//需要处理的值 for (j = 0; j < i; j++)//找合适的位置,太慢 { if (arr[j] > tmp) break; }//1 2 3 4 5 //把后面的数据往后移动 for (int k = i - 1; k >= j; k--) { arr[k + 1] = arr[k]; } //插入新数据 arr[j] = tmp; } } */ //希尔排序(时间复杂度:O(n^1.3~n^1.5),空间复杂度O(1),不稳定) //void Shell(int* arr, int len, int gap) //{ // int tmp;int j; // for (int i = gap; i < len; i ++) // { // tmp = arr[i]; // for ( j= i - gap; j >= 0; j -= gap) // { // if (arr[j] > tmp) // { // arr[j+gap] = arr[j]; // } // else // break; // } // arr[j+gap] = tmp; // } //} //void ShellSort(int* arr, int len) //{ // int d[] = { 5,3,1 }; // for (int i = 0; i < sizeof(d) / sizeof(d[0]); i++) // { // Shell(arr, len, i); // } //} //冒泡排序( O(n^2),O(1),稳定) //void Bubbler(int* arr, int len) //{ // int temp; // for (int i= 0; i < len-1; i++) // { // for (int j = 0; j + 1 < len - i; j++) // { // if (arr[j] > arr[j+1]) // { // temp = arr[j]; // arr[j] = arr[j+1]; // arr[j+1] = temp; // } // } // } //} //快速排序,O(nlogn),O(logn),不稳定 //int Partition(int* arr, int low, int high)//一次划分O(n),O(1) //{ // int tmp = arr[low];//基准 // while (low<high) // { // while (low<high && arr[high]>tmp) // { // high--; // } // if(low<high) // { // arr[low] = arr[high]; // } // while (low<high && arr[low]<=tmp) // { // low++; // } // if (low < high) // { // arr[high] = arr[low]; // } // } // arr[low] = tmp; // return low; //} // //void Quick(int* arr,int low,int high ) { // int par = Partition(arr, low, high); // if (low < par - 1) // { // Quick(arr, low, par - 1); // } // if (par + 1 < high) // { // Quick(arr, par + 1, high); // } //} //void QuickSort(int* arr, int len) //{ // Quick(arr, 0, len - 1);//加了一个马甲,目的为增加一个参数,解决参数不一致问题 //} //void QuickSort(int* arr, int len)//不能直接递归,所以舍去 //{ // int par=partition(arr,0,len-1) // if (0 < par - 1) // { // QuickSort(arr,len) // } //} //选择排序 (O(n^2),O(1),不稳定) //void SelectSort(int* arr, int len) //{ // int minlndex;//最小值的下标 // int tmp; // for (int i = 0; i < len - 1; i++) // { // minlndex = i; // for (int j = i + 1; j < len; j++) // { // if (arr[minlndex] > arr[j]) // { // minlndex = j; // } // } // //最小值和待排序的第一个值交换 // if (minlndex != i) // { // tmp = arr[minlndex]; // arr[minlndex] = arr[i]; // arr[i] = tmp; // } // // } //} //堆排序 //父-->子:i-->2*i+1,2*i+2 //子-->父:i-->(i-1)/2 //void HeapAdjust(int* arr, int start, int end) //{ // int tmp = arr[start]; // for (int i = 2 * start + 1; i <= end; i = 2*i+1) // { // if (i < end && arr[i] < arr[i + 1])//有右孩子,并且左孩子的值小于右孩子 // { // i++; // }//i一定是左右孩子的最大值 // if (arr[i] > tmp) // { // arr[start] = arr[i]; // start = i; // } // else // { // break; // } // } // arr[start] = tmp; //} // //void HeapSort(int* arr, int len) //{ // //第一次建立大根堆,从后往前,多次调整 // int i; // for (i = (len - 1 - 1) / 2; i >= 0; i--) // { // HeapAdjust(arr, i, len - 1); // } // //每次将根和待排序的最后一个做交换,然后再做调整 // int tmp; // for (i = 0; i < len; i++) // { // tmp = arr[0]; // arr[0] = arr[len - 1 - i]; // arr[len - 1 - i] = tmp; // // HeapAdjust(arr, 0, len - 1 - i-1); // } // //} //归并有序O(nlogn),O(n),稳定 // 一次归并 O(n) //void Merge(int* arr, int len, int gap) //{ // int low1 = 0;//第一段起始下标, // int high1 = low1 + gap-1;//第一段归并段的结束下标 // int low2 = high1 + 1;//第二个归并段的起始下标 // int high2 = low2 + gap-1<len-1?low2+gap-1:len-1;//第二个归并段的结束下标 // //brr,存放数据的数组 // int* brr = (int*)malloc(len * sizeof(int));//存放归并好的数据 // int i = 0;//brr的下标 // assert(brr != NULL); // //有两个归并段 // while (low2 < len) // { // //两个归并段都有数据 // while (low1<=high1&&low2<=high2) // { // if (arr[low1] <= arr[low2]) // { // brr[i++] = arr[low1++]; // } // else { // brr[i++] = arr[low2++]; // } // } // //一个归并段的数据已经完成了,另外一个还有数据 // while (low1<=high1) // { // brr[i++] = arr[low1++]; // } // while (low2<=high2) // { // brr[i++] = arr[low2++]; // } // //四个变量往后走,下两个归并段 // low1 = high2 + 1; // high1 = low1 + gap - 1; // low2 = high1 + 1; // high2 = low2 + gap < len ? low2 + gap - 1 : len - 1; // } // //2.只有一个归并段 // while (low1<len)//low1存在 // { // brr[i++] = arr[low1++]; // } // for (i = 0; i < len; i++)//将归并好的数据拷贝到arr中 // { // arr[i] = brr[i]; // } // free(brr);//不要忘记 //} //void MergeSort(int*arr,int len) //这块的时间复杂度是O(logn), //{ // for (int i = 1; i < len; i*=2) // { // Merge(arr, len, i); // } //} //基数排序(桶排序) 适用于n很大,d较小的序列 (O(d*n)(d指的是进几次出几次),O(n),稳定) //获取十进制整数右树第figur位的数字 //static int GetNum(int n,int figur) //{ // for (int i = 0; i < figur; i++) // { // n /= 10; // // } // return n % 10; //} //static int GetFigur(int* arr, int len) //{ // int max = arr[0]; // for (int i = 1; i < len; i++) // { // if (max < arr[i]) // { // max = arr[i]; // } // } // // int count = 0; // while (max != 0) // { // count++; // max /= 10; // } // return count; //} //void RadixSort(int* arr, int len) //{ // //需要10个链式队列,存放进队的数字 // LinkQueue queArr[10];//定义了10个队头 // for (int i = 0; i < 10; i++) // { // InitQueue(&queArr[i]);//初始化 // } // //得到最大数字的位数,确定进队和出队的次数 // int count = GetFigur(arr, len); // int index;//队列的下标 // for (int i = 0; i < count; i++)//1.趟数2.处理每个数字从右往左的第i个数字 // { // for (int j = 0; j < len; j++)//遍历数组并进队 // { // index = GetNum(arr[j], i);//index保存arr[j]应该进入的队的队列下标 // Push(&queArr[index],arr[j]);//将数字存放在对应的队列 // } // //出队 // int j = 0; // for(int k = 0; k < 10; k++) // { // while (!IsEmpty(&queArr[k])) // { // DeQueue(&queArr[k], &arr[j++]); // } // } // //销毁 // for (int i = 0; i < 10; i++) // { // Destroy(&queArr[i]); // } // } //} void Show(int* arr, int len) { for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = { 4,6,8,9,2,34,56,7,12,66,99,36,87 }; //InsertSort(arr,sizeof(arr)/sizeof(arr[0])); //ShellSort(arr, sizeof(arr) / sizeof(arr[0])); //Bubbler(arr, sizeof(arr) / sizeof(arr[0])); //QuickSort(arr, sizeof(arr) / sizeof(arr[0])); //SelectSort(arr, sizeof(arr) / sizeof(arr[0])); //HeapSort(arr, sizeof(arr) / sizeof(arr[0])); //MergeSort(arr, sizeof(arr) / sizeof(arr[0])); //RadixSort(arr, sizeof(arr) / sizeof(arr[0])); Show(arr, sizeof(arr) / sizeof(arr[0])); return 0; }
1.对列头文件名命为"listqueue.h"
//这是队列的头文件 #pragma once typedef int ElemType; typedef struct QNode { ElemType data; struct QNode* next; }QNode ,*QueuePtr; typedef struct { QNode* front;//队头指针 QNode* rear;//队尾指针 }LinkQueue;//头结点的定义 //队列初始化 void InitQueue(LinkQueue* pq); //入队 bool Push(LinkQueue* pq, ElemType val); //判空 bool IsEmpty(LinkQueue* pq); //获取队头元素,但不删除 bool GetHead(LinkQueue* pq, ElemType* rtval); //出队,获取队头元素,且删除 bool DeQueue(LinkQueue* ps, ElemType* rtval); //销毁 void Destroy(LinkQueue* ps);
2.队列函数实现名命为listqueue.cpp
//桶排序需要用到队列 //这是队列的函数实现 #include<stdio.h> #include<stdlib.h> #include<assert.h> #include"listqueue.h" //队列初始化 void InitQueue(LinkQueue* pq) { assert(pq != NULL); if (pq == NULL) return; pq->front = NULL; pq->rear=NULL; } //入队 bool Push(LinkQueue* pq, ElemType val) { QNode* p = (QNode*)malloc(sizeof(QNode)); assert(p != NULL); if (p == NULL) return false; p->data = val; p->next = NULL; if (!IsEmpty(pq)) { pq->rear->next = p; pq->rear = p; } else { pq->rear = p; pq->front = p; } return true; } //判空 bool IsEmpty(LinkQueue* pq) { return pq->front == NULL;//队头都没有元素 } //获取队头元素,但不删除 bool GetHead(LinkQueue* pq, ElemType* rtval) { assert(pq != NULL); if (pq == NULL) return false; *rtval = pq->front->data; return true; } //出队,获取队头元素,且删除 bool DeQueue(LinkQueue* pq, ElemType* rtval) { assert(pq != NULL); if (pq == NULL) return false; *rtval = pq->front->data; QNode* p = (QNode*)malloc(sizeof(QNode)); p = pq->front; pq->front = p->next; free(p); if (pq->front == NULL) pq->rear == NULL; return true; } //销毁 void Destroy(LinkQueue* pq) { QNode* p ; while (pq->front!=NULL) { p = pq->front; pq->front = p->next; free(p); } pq->rear == NULL; }
C语言数据结构8大排序
最新推荐文章于 2022-10-04 19:20:43 发布