蝶形变换初试序列

问题描述:
处理音频信号是经常用到傅里叶变换将时域波形转变为频域波形,而 FFT 是快速计算这一变换的一个方法。基 2 时域抽选法是一个时间 FFT 的方法,通过按数字下标的奇偶分组,可以获得蝶形变换的初试序列。请模拟这个过程。


关于输入:
第一行表示输入的组数T,

每组的第一行是一个整数 k(1<=k<=12), 表示数列长度为 2^k 。然后接着一行是待分组的数列,元素的大小范围为 [0,10000].

关于输出:
分组后输出。


样例输入:
1
3
1 3 5 7 11 13 17 19
样例输出:
1 11 5 17 3 13 7 19


提示:
比如数列长度为 8 ,奇偶分组如下:
初始: 0 1 2 3 4 5 6 7
第一次分组: 0 2 4 6 1 3 5 7
然后接着 分别对分开的两组 再进行奇偶分组,再得到:
0 4 2 6 1 5 3 7
再分组是数列不再变化,这就是进行基 2 时域抽选法的初试序列。



思路:

对组内元素进行奇偶项分组,假设对n个元素分组,则奇偶边界为m=n/2;再对m个数据进行分组,边界为m=m/2;以此类推

若用树状图可表示如下:


即,假设原始队列有32个元素,每经过一次分组分为2x16;

定义butterflyTrans(int E[], int n)为一次分组,E[]存储原始队列,n为队列长度(每一组有n个元素),运用递归思想,每一次分组n=n/2,直到n==0(每组元素个数为1时,队列不再变换);此时递归走过的路径为上图黑色数字部分(从32到2);

扫描二维码关注公众号,回复: 6086212 查看本文章

递归返回部分是上图红色部分(从2到16,指每组内元素的个数),但详细路径是2—4,此时4可再分为两组(图中省略),当做完其中一组的奇偶划分后,返回到另一组,即此时是从4—2,而非4—8;

同理当红字4部分分组完后,返回到8,再从8分两个四组,四组中再分两个二组,以此类推,详细的递归返回应是2—4—2—8—2—4—2—16—2—4—2—8—2—4—2(......);

由上述数据得出的规律是:

int fir = pow(2, p);
if ((c + fir) % (2 * fir) == 0)
{
return 2 * fir;

}

其中p范围从1到k-1(次幂),2*fir即为每一次递归返回时,当前组的待分组元素个数;

c为每一轮递归返回的计数器,与返回结果息息相关,c为奇数时均返回2(c为偶数时按照上述代码);


(实在是对递归不太熟悉,一层一层很晕,用了笨方法,望大佬们多多指教)


代码如下:

#include <iostream>
using namespace std;


int buf[4200];
int temp[4200];
int k;


int subCount(int quality, int c)  //quality代表次幂,c表示计数器count
{
if (c%2!=0)
{
return 2;
}
else
{
for (int p = 1; p < quality; p++)
{
if (c == pow(2, quality - 1))
{
return 0;  //递归结束
}
else
{
int fir = pow(2, p);
if ((c + fir) % (2 * fir) == 0)
{
return 2 * fir;
}
}
}
}
}


void butterflyTrans(int E[],int n,int count)
{
    int m = n / 2;   //m是奇偶边界
int x = 0;
if (m!=0)
{
for (int i = 0; i < n; i++)
{
if (i % 2 != 0)   //奇数项
{
x = E[i];
temp[m + i / 2] = E[i];  //m是奇偶边界
}
else   //偶数项
{
x = E[i];
temp[i / 2] = E[i];
}
}  //完成一轮蝶形变换,将n个数分为两组,一组m个数
for (int index = 0; index < n; index++)   //更新原数组
{
E[index] = temp[index];
}
butterflyTrans(E, m, count);
}
else
{
count++;
int ret = subCount(k, count);
if (ret==0)
{
return;
}
else
{
return butterflyTrans(E+2*n,ret,count);
}
//每轮返回位置
}


}


int main()
{
int T;
cin >> T;
while (T!=0)
{
cin >> k;
for (int j = 0; j < pow(2,k); j++)
{
cin >> buf[j];
}
butterflyTrans(buf, pow(2, k), 0);
for (int p = 0; p < pow(2,k); p++)
{
cout << buf[p] << " ";
}
cout << endl;
T--;
}
}


猜你喜欢

转载自blog.csdn.net/qq_29442755/article/details/79682849