标签:位置 想法 ace printf img 根据 ret maps ack
Radix Sort。实现桶式排序和基于桶式排序的基数排序。在基数 B 中,数组长度 n 和 最大元素 m 中,对排序时间影响最大的是哪一个?元素在未排序数组中的顺序是否对时间复杂度有影响?设计实验证明你的想法。
Stack。用 C 语言设计堆栈,并实现中缀表达式到后缀表达式的转换。
对于桶排序,其算法实现为:使用一个大小为 \(M\) 的名为 \(Count\) 的数组,它被初始化为全部为 0.于是,\(Count\) 有 \(M\) 个单元(即桶),这些桶初始化为空。当读入 \(A_i\) (\(A_1, A_2..., A_N\) 为小于 \(M\) 的输入数据,且为正整数),\(Count[A_i]\) 增 1。在所有的输入数据读入后,扫描数组 \(Count\),打印出排序后的数组。
对于基数排序,其算法实现为:将整数按位数切割成不同的数字,然后按每个位数分别比较。具体操作是将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
算法主要利用堆栈,算法实现为:
从头到尾读取中缀表达式中的每个对象,对不同对象按不同的情况处理。
/**
* 桶式排序
* @param A 待排序数组
* @param m 最大元素
* @param n 数组长度
*/
void BucketSort(int *A, int m, int n)
{
int B[m + 1];
int i, j, count = 0;
memset(B, 0, (m + 1) * sizeof(int)); // 数组初始化
for (i = 0; i < n; i++)
{
j = A[i];
B[j] += 1; // 记录该桶中元素个数
}
// 把桶中的元素按顺序依次放入原数组中
for (i = 0; i <= m; i++)
{
if (B[i] > 0) // 该桶不为空
{
for (j = 0; j < B[i]; j++)
{
A[count] = i;
count++;
}
}
}
}
/**
* 利用计数排序的基数排序
* @param A 待排数组
* @param n 数组元素个数
*/
void RadixSort(int *A, int n)
{
int exp; // 指数,当对数组按照个位数进行排序时,exp = 1,按十位数排序时,exp = 10...
int max = 0;
// 获取数组最大值
for (int i = 0; i < n; i++)
{
if (A[i] > max)
max = A[i];
}
// 从个位数开始,对数组进行按位排序
for (exp = 1; max / exp > 0; exp *= 10)
{
int tmp[n]; // 存储“被排序数据”的临时数组
int i, buckets[10];
memset(buckets, 0, 10 * sizeof(int)); // 数组初始化为 0
// 存储数据出现的次数
for (i = 0; i < n; i++)
buckets[(A[i] / exp) % 10]++;
// 将 buckets[i] 更新为前面所有元素的个数之和,即,buckets[i] 中存储的是其对应的数据在 tmp[] 中的位置,即最终此趟排序下来后数据在 A[] 中的位置
for (i = 1; i < 10; i++)
buckets[i] += buckets[i - 1];
// 将数据存储到临时数组 tmp[] 中
for (i = n - 1; i >= 0; i--)
tmp[--buckets[(A[i] / exp) % 10]] = A[i];
// 将排好的数据赋值给 A[]
for (i = 0; i < n; i++)
A[i] = tmp[i];
}
}
// 获取字符的优先值
int Priority(char op)
{
int priority;
if (op == ‘*‘ || op == ‘/‘)
priority = 2;
if (op == ‘+‘ || op == ‘-‘)
priority = 1;
if (op == ‘(‘)
priority = 0;
return priority;
}
bool TransEX(char *str, char * str1)
{
Stack S = CreateStack();
int i, j = 0;
for (i = 0; str[i] != ‘#‘; i++)
{
if ((str[i] >= ‘0‘ && str[i] <= ‘9‘) || (str[i] >= ‘a‘ && str[i] <= ‘z‘)) // 数字或者字母直接入栈
str1[j++] = str[i];
else // 不是数字或者字母
{
if (IsEmpty(S)) // 栈空则入栈
Push(str[i], S);
else if (str[i] == ‘(‘) // 左括号入栈
Push(str[i], S);
else if (str[i] == ‘)‘) // 如果是右括号,只要栈顶不是左括号,就弹出并输出
{
while (Top(S) != ‘(‘)
{
str1[j++] = Top(S);
Pop(S);
}
Pop(S); // 弹出左括号
}
else
{
while (Priority(str[i]) <= Priority(Top(S))) // 栈顶优先级大于等于当前运算符,则输出
{
str1[j++] = Top(S);
Pop(S);
if (IsEmpty(S))
break;
}
Push(str[i], S); // 把当前运算符压栈
}
}
}
while (!IsEmpty(S))
{
str1[j++] = Top(S);
Pop(S);
}
str1[j] = ‘#‘;
DisposeStack(S);
return true;
}
原数组的长度为 \(N\),所以需要扫描 \(N\) 次,之后在重新赋值给原数组时,又对 \(M\) 只桶进行了扫描,因此,总的时间复杂度为 \(O(M + N)\)。
基数排序中主要为一个二重循环,其中,外层循环的次数是待排序数字中最大值的位数,内层有四个时间复杂度为 \(O(n)\) 的一重循环,其总体可以看成 \(O(n)\),因此,基数排序的时间复杂度为 \(O(k \ · \ n)\),其中 \(n\) 是待排序元素的个数,\(k\) 是数字的位数。
从算法的实现中,我们可以看出其时间复杂度是线性的,每一次循环处理一个字符,因此其时间复杂度为 \(O(N)\)。
根据实验结果,可以证明上面的分析的正确性。
#include <stdio.h>
#include "string.h"
/**
* 桶式排序
* @param A 待排序数组
* @param m 最大元素
* @param n 数组长度
*/
void BucketSort(int *A, int m, int n)
{
int B[m + 1];
int i, j, count = 0;
memset(B, 0, (m + 1) * sizeof(int)); // 数组初始化
for (i = 0; i < n; i++)
{
j = A[i];
B[j] += 1; // 记录该桶中元素个数
}
// 把桶中的元素按顺序依次放入原数组中
for (i = 0; i <= m; i++)
{
if (B[i] > 0) // 该桶不为空
{
for (j = 0; j < B[i]; j++)
{
A[count] = i;
count++;
}
}
}
}
/**
* 利用计数排序的基数排序
* @param A 待排数组
* @param n 数组元素个数
*/
void RadixSort(int *A, int n)
{
int exp; // 指数,当对数组按照个位数进行排序时,exp = 1,按十位数排序时,exp = 10...
int max = 0;
// 获取数组最大值
for (int i = 0; i < n; i++)
{
if (A[i] > max)
max = A[i];
}
// 从个位数开始,对数组进行按位排序
for (exp = 1; max / exp > 0; exp *= 10)
{
int tmp[n]; // 存储“被排序数据”的临时数组
int i, buckets[10];
memset(buckets, 0, 10 * sizeof(int)); // 数组初始化为 0
// 存储数据出现的次数
for (i = 0; i < n; i++)
buckets[(A[i] / exp) % 10]++;
// 将 buckets[i] 更新为前面所有元素的个数之和,即,buckets[i] 中存储的是其对应的数据在 tmp[] 中的位置,即最终此趟排序下来后数据在 A[] 中的位置
for (i = 1; i < 10; i++)
buckets[i] += buckets[i - 1];
// 将数据存储到临时数组 tmp[] 中
for (i = n - 1; i >= 0; i--)
tmp[--buckets[(A[i] / exp) % 10]] = A[i];
// 将排好的数据赋值给 A[]
for (i = 0; i < n; i++)
A[i] = tmp[i];
}
}
int main()
{
int i;
// 桶式排序测试
int a0[10] = {7,8,5,4,1,6,12,14,10,11};
printf("桶式排序 Before sort: \n");
for (i = 0; i < 10; i++)
printf("%d ", a0[i]);
printf("\n");
BucketSort(a0, 54, 10);
printf("桶式排序 After sort: \n");
for (i = 0; i < 10; i++)
printf("%d ", a0[i]);
printf("\n");
printf("-----------------------\n");
// 基数排序测试
int a[10] = {64,8,216,512,27,729,0,1,343,125};
printf("基数排序 Before sort: \n");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
RadixSort(a, 10);
printf("基数排序 After sort: \n");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include "stdbool.h"
// 获取字符的优先值
int Priority(char op)
{
int priority;
if (op == ‘*‘ || op == ‘/‘)
priority = 2;
if (op == ‘+‘ || op == ‘-‘)
priority = 1;
if (op == ‘(‘)
priority = 0;
return priority;
}
bool TransEX(char *str, char * str1)
{
Stack S = CreateStack();
int i, j = 0;
for (i = 0; str[i] != ‘#‘; i++)
{
if ((str[i] >= ‘0‘ && str[i] <= ‘9‘) || (str[i] >= ‘a‘ && str[i] <= ‘z‘)) // 数字或者字母直接入栈
str1[j++] = str[i];
else // 不是数字或者字母
{
if (IsEmpty(S)) // 栈空则入栈
Push(str[i], S);
else if (str[i] == ‘(‘) // 左括号入栈
Push(str[i], S);
else if (str[i] == ‘)‘) // 如果是右括号,只要栈顶不是左括号,就弹出并输出
{
while (Top(S) != ‘(‘)
{
str1[j++] = Top(S);
Pop(S);
}
Pop(S); // 弹出左括号
}
else
{
while (Priority(str[i]) <= Priority(Top(S))) // 栈顶优先级大于等于当前运算符,则输出
{
str1[j++] = Top(S);
Pop(S);
if (IsEmpty(S))
break;
}
Push(str[i], S); // 把当前运算符压栈
}
}
}
while (!IsEmpty(S))
{
str1[j++] = Top(S);
Pop(S);
}
str1[j] = ‘#‘;
DisposeStack(S);
return true;
}
int main()
{
char *infix = malloc(20 * sizeof(char));
char *postfix = malloc(20 * sizeof(char));
printf("请输入中缀表达式(以 “#” 结束):\n");
fflush(stdout);
scanf("%s", infix);
TransEX(infix, postfix);
printf("后缀表达式为:\n");
// 打印转换好的字符串
for (int i = 0; postfix[i] != ‘#‘ ; i++)
{
printf("%c", postfix[i]);
}
return 0;
}
typedef char ElementType;
#ifndef _Stack_h
#define _Stack_h
struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode Stack;
int IsEmpty(Stack S);
Stack CreateStack(void);
void DisposeStack(Stack S);
void MakeEmpty(Stack S);
void Push(ElementType X, Stack S);
ElementType Top(Stack S);
void Pop(Stack S);
ElementType TopAndPop(Stack S);
#endif
#include "stack.h"
#include "fatal.h"
#include <stdlib.h>
// 节点
struct Node
{
ElementType Element;
PtrToNode Next;
};
// 判断栈是否为空,判断方法为判断头节点S指向的下一个节点是否为空
int
IsEmpty(Stack S)
{
return S->Next == NULL;
}
// 创建一个栈,主要是创建一个头节点
Stack
CreateStack(void)
{
Stack S;
S = malloc(sizeof(struct Node));
if (S == NULL)
FatalError("Out of space!!!"); // 空间用尽警告
S->Next = NULL;
MakeEmpty(S);
return S;
}
// 创建一个空栈
void
MakeEmpty(Stack S)
{
if (S == NULL)
Error("Must use CreateStack first");
else
while (!IsEmpty(S))
Pop(S);
}
// 处理掉这个栈,即清空所有元素并释放头节点
void
DisposeStack(Stack S)
{
MakeEmpty(S);
free(S);
}
// 进栈操作
void
Push(ElementType X, Stack S)
{
PtrToNode TmpCell;
TmpCell = malloc(sizeof(struct Node));
if (TmpCell == NULL)
FatalError("Out of space!!!");
else
{
TmpCell->Element = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
}
}
// 返回栈顶元素
ElementType
Top(Stack S)
{
if (!IsEmpty(S))
return S->Next->Element;
Error("Empty stack");
return 0;
}
// 弹出栈顶元素
void
Pop(Stack S)
{
PtrToNode FirstCell; // 第一个单元,即栈顶
if (IsEmpty(S))
Error("Empty stack");
else
{
FirstCell = S->Next;
S->Next = S->Next->Next;
free(FirstCell);
}
}
ElementType TopAndPop(Stack S)
{
ElementType res = Top(S);
Pop(S);
return res;
}
#include <stdio.h>
#include <stdlib.h>
#define Error( Str ) FatalError( Str )
#define FatalError( Str ) fprintf( stderr, "%s\n", Str ), exit( 1 )
标签:位置 想法 ace printf img 根据 ret maps ack
原文地址:https://www.cnblogs.com/fanlumaster/p/13882154.html