排序算法----基数排序(RadixSort(L,max))单链表版本

转载http://blog.csdn.net/Shayabean_/article/details/44885917博客

先说说基数排序的思想

基数排序是非比较型的排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。在每一次排序中,按照当前位把数组元素放到对应

的桶当中,然后把桶0到桶9中的元素按先进先出的方式放回数组中。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

这个版本的基数排序RadixSort(L,max)较RadixSort(L)不同的是需要输入待排序列最大数的位数。因为RadixSort(L)最大数位在程序中已经计算过了,因为需要计算最大数,所以需要对待排链表最开始循环一次,所以RadixSort(L,max)速度比RadixSort(L)稍快。

这篇博客包括4个文件,两个头文件RadixSort.h和fatal.h,一个库函数RadixSort.c,和一个测试文件Test_Radix_Sort.c

头文件fatal.h:

1 #include<stdio.h>
2 #include<stdlib.h>
3 #define Error(Str) FatalError(Str)
4 #define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1);

头文件RadixSort.h

 1 typedef int ElementType;
 2 #ifndef RADIX_SORT_H
 3 #define RADIX_SORT_H
 4
 5 #include<stdbool.h>
 6 #define ListEmpty -2
 7
 8 struct Node;
 9 typedef struct Node *PtrToNode;
10 typedef PtrToNode List;
11 typedef PtrToNode Position;
12
13 List MakeEmpty(List L);
14 bool IsEmpty(List L);
15 bool IsLast(Position P, List L);
16 Position Header(List L);
17 Position Advance(Position P);
18 ElementType Retrieve(Position P);
19 void DeleteList(List L);
20 void PrintList(const List L);
21 void Insert(ElementType X, List L, Position P);
22 void MoveNode(List L1, List L2);//将表L2中的头节点移动成为L1的尾节点
23 void RadixSort(List L,int max);//最终基数排序函数,输入链表L,将L排序得到新的排序链表L,其中max是待排元素最高有多少位
24 #endif // !RADIX_SORT_H

其中RadixSort是最终排序函数,调用它即可排序。

库函数RadixSort.c

  1 #include "RadixSort.h"
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<malloc.h>
  5 #include<math.h>
  6 #include"fatal.h"
  7 struct Node
  8 {
  9     ElementType Element;
 10     Position Next;
 11 };
 12
 13 //初始化链表
 14 List MakeEmpty(List L)
 15 {
 16     if (L != NULL)
 17         DeleteList(L);//如果链表非空,则删除链表
 18     L = malloc(sizeof(struct Node));
 19     if (L == NULL)
 20         FatalError("Out of memory!");
 21     L->Next = NULL;
 22     return L;
 23 }
 24 //判断链表是否为空
 25 bool IsEmpty(List L)
 26 {
 27     return L->Next == NULL;
 28 }
 29
 30 //判断当前指针P是否指向链表最后一个元素
 31 bool IsLast(Position P, List L)
 32 {
 33     return P->Next == NULL;
 34 }
 35
 36 //获取链表头
 37 Position Header(List L)
 38 {
 39     return L;
 40 }
 41
 42 //获取位置P的下一个位置
 43 Position Advance(Position P)
 44 {
 45     return P->Next;
 46 }
 47
 48 //提取位置P处结构里面的值
 49 ElementType Retrieve(Position P)
 50 {
 51     return P->Element;
 52 }
 53
 54 //删除链表
 55 void DeleteList(List L)
 56 {
 57     Position P, Temp;
 58     P = L->Next;
 59     L->Next = NULL;
 60     while (P != NULL)
 61     {
 62         Temp = P->Next;
 63         free(P);
 64         P = Temp;
 65     }
 66 }
 67
 68 //打印链表
 69 void PrintList(const List L)
 70 {
 71     Position P = Header(L);
 72     if (IsEmpty(L))
 73         printf("Empty list\n");
 74     else
 75     {
 76         do
 77         {
 78             P = Advance(P);
 79             printf("%d ", Retrieve(P));
 80         } while (!IsLast(P, L));
 81         printf("\n");
 82     }
 83 }
 84
 85 //插入元素X到位置P后面
 86 void Insert(ElementType X, List L, Position P)
 87 {
 88     Position  TmpCell;
 89     TmpCell = malloc(sizeof(struct Node));
 90     if (TmpCell == NULL)
 91         FatalError("Out of Space!!!");
 92     TmpCell->Element = X;
 93     TmpCell->Next = P->Next;
 94     P->Next = TmpCell;
 95 }
 96
 97 void MoveNode(List L1, List L2)
 98 {
 99     //将表L2中的头节点移动成为L1的尾节点
100     Position Tmp1 = L1;
101     Position Tmp2;
102     if (IsEmpty(L2)) exit(ListEmpty);
103     while (!IsLast(Tmp1,L1))
104         Tmp1 = Tmp1->Next;//使Tmp1指向L1表尾
105     Tmp2 = L2->Next;
106     L2->Next = Tmp2->Next;
107     Tmp1->Next = Tmp2;
108     Tmp2->Next = NULL;
109 }
110
111 void RadixSort(List L,int max)
112 {
113     //if (IsEmpty(L)) return L; //如果要排序的链表L是空表,则不排序
114     int i,j, TmpSub;//Tmpsub存储数的个位、十位、百位
115     ElementType FirstElement;//存储链表的第一个元素
116
117     List Bucket[10];//开辟10个桶,依次为0~9
118     for (i = 0; i < 10; i++) Bucket[i] = MakeEmpty(NULL);//对10桶进行初始化,每一个数组都是一个链表
119     for (i = 0; i < max; i++)//开始提取每一位数的个位、十位、百位
120     {
121         while (!IsEmpty(L))//当L中的元素被取光了,则循环结束
122         {
123             FirstElement = L->Next->Element;//取出第一个节点的数据
124             TmpSub = (int)(FirstElement / pow(10, i)) % 10;//依次取出个十百位数字
125             MoveNode(Bucket[TmpSub], L);//将L中的节点依次移到对应的桶中
126         }
127         for (j = 0; j < 10; j++)    //将桶中的数再次移动到L中
128         {
129             while (!IsEmpty(Bucket[j])) MoveNode(L, Bucket[j]);
130         }
131     }
132     for (i = 0; i < 10; i++) free(Bucket[i]) ;//释放掉10个桶
133 }

测试函数Test_Radix_Sort.c

 1 #include<stdio.h>
 2 #include "RadixSort.h"
 3 #include"fatal.h"
 4 #include<time.h>
 5
 6 int main()
 7 {
 8     int  amount;
 9     ElementType TmpElement;
10     List L; Position P;
11     L = MakeEmpty(NULL);//初始化链表
12     P = L;
13     if (L == NULL) Error("Out of Space!!!");
14     printf("随机生成多少位数:");
15     scanf_s("%d", &amount);
16     srand((unsigned)time(NULL));
17     for (int i = 0; i < amount; i++)
18     {
19         Insert(rand() % 10000, L, P);
20         P = Advance(P);
21     }
22     printf("排序前的结果:");
23     PrintList(L);
24     RadixSort(L,4);//调用排序函数排序
25     printf("基数排序后的结果:");
26     PrintList(L);
27 }

时间: 2024-10-13 12:43:15

排序算法----基数排序(RadixSort(L,max))单链表版本的相关文章

数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点

题目: 给定一个单链表,只给出头指针head: 1.如何判断是否存在环? 2.如何知道环的长度? 3.如何找出环的连接点在哪里? 4.带环链表的长度是多少? 解法: 1.对于问题1,使用追赶的方法,设定两个指针slow.fast,从头指针开始,每次分别前进1步.2步.如存在环,则两者相遇:如不存在环,fast遇到NULL退出. 2.对于问题2,记录下问题1的碰撞点p,slow.fast从该点开始,再次碰撞所走过的操作数就是环的长度s. 3.问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的

经典排序算法 - 基数排序Radix sort

经典排序算法 - 基数排序Radix sort 原理类似桶排序,这里总是需要10个桶,多次使用 首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数 例如 待排序数组[62,14,59,88,16]简单点五个数字 分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样 |  0  |  0  | 62 |  0  | 14 |  0  | 16 |  0  |  88 | 59 | |  0  |  1  |  2  |  3  |  4 | 

算法题——二叉树转换为左单链表

题目:给定一棵二叉树,将所有的结点都放到左儿子的位置,即除了root结点外,每一个结点都是其他某一个结点的左儿子.不用保持某种顺序,不能递归,O(1)空间. 思路: 我的想法是,维持一个遍历指针p,另一个指针tail永远指向向左遍历到底的结点: 初始化p和tail都为root,开始循环: 如果p为叶子结点,则退出循环: 如果p没有右儿子,则向左下降一层: 如果p有右儿子,则tail向左遍历到底,将p的右子树挂到tail的左儿子上,p右儿子赋空值,然后向左下降一层. p每次下降一层时,tail从上

学习排序算法(一):单文档方法 Pointwise

学习排序算法(一):单文档方法 Pointwise 1. 基本思想 这样的方法主要是将搜索结果的文档变为特征向量,然后将排序问题转化成了机器学习中的常规的分类问题,并且是个多类分类问题. 2. 方法流程 Pointwise方法的主要流程例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHVxdXRvZ2V0aGVy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity

排序算法----基数排序(RadixSort(L))单链表智能版本

转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较. 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零.然后,从最低位开始,依次进行一次排序.在每一次排序中,按照当前位把数组元素放到对应 的桶当中,然后把桶0到桶9中的元素按先进先出的方式放回数组中.这样从最低位排序一直到最高位排序完成以后,

数据结构与算法系列(1)-单链表类的实现(C++)

通过定义一个C++类封装单链表这种数据结构, 封装的方法有: 1.通过输入创建单链表: 2.获取单链表的数据元素个数: 3.打印输出单链表中各个元素: 4.搜索某个元素在单链表中的位置: 5.在某个位置之后插入一个结点: 6.在某个位置删除一个节点: 7.单链表逆置: 8.单链表是否存在回环的判定: 9.单链表的升序排序: 10.两个单链表的升序合并: 11.两个单链表的降序合并. 注:单链表的排序采用的是快速排序的方法. 下面是C++写的程序代码,附运行截图. #include <iostre

常见算法题:逆置单链表

思路:使用头插法建立单链表,每插入一个节点都插在头结点之后,先使头结点指向NULL,再将剩余结点使用头插法建表,即可实现单链表逆置. 代码: 设目标单链表L,结点为int类型 void Reverse(LinkList &L) { int *p = L.head->next,*q; L.head->next = NULL; while(p!=NULL) { q = p->next; p->next = L.head->next; L.head->next = p

算法习题---线性表之单链表逆序打印

一:题目 逆序打印单链表中的数据,假设指针指向单链表的开始结点 二:思路 1.可以使用递归方法,来进行数据打印 2.可以借助数组空间,获取长度,逆序打印数组 3.若是可以,对链表数据使用头插法,逆序排列,然后正序打印即可 三:算法实现(这里使用方法一:递归实现简单易懂) #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 #define OK 1 #def

算法习题---线性表之单链表的查找

一:问题 已知一个带头结点的单链表,结点结构为(data,link)假设该链表只给出了头指针list,在不改变链表的前提下,设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数),若查找成功,算法输出该结点的data域的值,并返回1,否则,只返回0. 注意: 这里的链表中没有给出链表长度哟 二:思路 设置两个指针p.q,分别指向该链表的第一个元素(头结点的下一个元素)和头结点,一个整数num(初值为1),p向后移动一个位置num值加1,如果num值大于k,则p,q一起移动,p移