打印

C算法大讨论:关于数组移动的,每次都更新一个数

[复制链接]
6148|53
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 gudeng614 于 2010-5-11 16:25 编辑

已知一个数组A[8];
第一次输入A[0]=1;要求得到A[0]=1;
第二次输入A[0]=2;要求得到A[0]=2,A[1]=1;
第三次输入A[0]=3,要求得到A[0]=3,A[1]=2,A[2]=1;
第四次输入A[0]=4,要求得到A[0]=4,A[1]=3,A[2]=2,A[3]=1;

。。。。。。
第八次输入A[0]=8,要求得到A[0]=8,A[1]=7,A[2]=6,A[3]=5,A[4]=4,A[5]=3,A[6]=2,A[7]=1;
A[0]每一次都更新,其它依次前移
谢谢各位了,

相关帖子

沙发
ayb_ice| | 2010-5-11 16:13 | 只看该作者
没有看懂要求

使用特权

评论回复
板凳
sxfyyy| | 2010-5-11 16:42 | 只看该作者
我也想知道,往高手不吝赐教

使用特权

评论回复
地板
xuyiyi| | 2010-5-11 18:58 | 只看该作者
不知你这种数组使用在什么场合,一般来说,这种类型数组移动处理用指针模拟栈操作效率较高,程序如下:
  unsigned char  A[8];
  unsigned char  *p;
   p   = A;
  *p  = 1;
  ++*p = 2;
  ++*p = 3;
  ++*p = 4;
  ++*p = 5;
  ++*p = 6;
  ++*p = 7;
  ++*p = 8;

此时指向数组A[8]的地址指针是浮动的,即时状态下的*p相当于A[0];--*p相当于A[1];依次类推......

使用特权

评论回复
5
冷漠| | 2010-5-11 19:21 | 只看该作者
LS的程序结果成了:
unsigned char  A[8]={1,2,3,4,5,6,7,8};

那费那么大劲儿干吗:直接初始化就完了。——和题意不符。没有体现移动。
LZ的意思是8次输入:
1;
2,1;
3,2,1;
4,3,2,1;
5,4,3,2,1;
......
8,7,6,5,4,3,2,1;

使用特权

评论回复
6
冷漠| | 2010-5-11 20:13 | 只看该作者
咱菜鸟试试:

使用特权

评论回复
7
索伦之眼| | 2010-5-11 20:40 | 只看该作者
一般分两种解决方法:
1.以时间换空间
2.以空间换时间

我们一般采用“以空间换时间”的方法(即多占点内存,获得高的执行效率):
将数组大小设为m组。(ps: m越大,这种方法越有优势,如100000组数据,都能这么干,避免频繁移动~)
//数据库数组
int data[m];//数据存储区
int nNowNum = 0;//当前存储序号
//存储数据,参数newData为需要保存的数据
void savedata(int newData)
{
    nNowNum ++;
    nNowNum %= m;
    data[nNowNum] = newData;
}
//根据序号获取数据
int getdata(int nNum)
{
    return data[(nNowNum+nNum)%m];
}

有更好的解法,请指教~

使用特权

评论回复
8
呆板书生| | 2010-5-11 22:12 | 只看该作者
这个嘛,回家按按自己的计算器就知道怎么回事了

使用特权

评论回复
9
highgear| | 2010-5-11 22:19 | 只看该作者
顶 8 楼的 circular buffer. m 最好使用 2^N, 这样可以避免使用 % :
nNowNum &=  _2_Power_N - 1;
小一些的数组简单的下移就可以, 一些 cpu 支持块移动, 效率也不低。  
这种问题无须什么"大讨论". 自己写一个,不费什么功夫:
for (i=m-1; i>0; i--)
  a[i] = a[i-1]

使用特权

评论回复
10
wangwo| | 2010-5-11 22:22 | 只看该作者
想倒着装进去啊,以前用一个软件做过,不是编程

使用特权

评论回复
11
xuyiyi| | 2010-5-12 07:03 | 只看该作者
数组不大,计算量也不大,7楼 冷漠大师的方法较好,程序简洁,结构清楚。
如果数组较大,计算量成几何级的增大,8楼 索伦之眼大师的方法较好,体现了较高的执行效率。

使用特权

评论回复
12
mohanwei| | 2010-5-12 08:47 | 只看该作者
用一个类/结构来维护一个环形缓冲区就行了,例如:
int start_pos;//“数组”起始位置
int end_pos;//“数组”结束位置
int len;//“数组”长度
unsigned char buff[1024];//存放“数组”
操作时直接修改start_pos,并将新输入的数放入新单元即可。

使用特权

评论回复
13
mohanwei| | 2010-5-12 08:50 | 只看该作者
数组移动不管用什么方法,效率都是很低的。如果跑在上位机平台,更是极其低下,因为OS会带来很多额外的开销。

使用特权

评论回复
14
程序匠人| | 2010-5-12 10:18 | 只看该作者
按题意理解,标准答案应该是6楼;并且实现起来比较简单且容易理解。

如果撇开题意,老许所提的方法在理念上更科学。
须知:运动是相对的。物理空间如此,数据空间也如此。
所以与其移动数据,不如移动指针。:)

当然,最终用哪种方法,可具体情况具体分析。

使用特权

评论回复
15
xbp| | 2010-5-12 10:41 | 只看该作者
for(i=9;i>0;i--)        cal_data[i]=cal_data[i-1];
cal_data[0]=0x11;

使用特权

评论回复
16
aresc| | 2010-5-12 10:53 | 只看该作者
本帖最后由 aresc 于 2010-5-12 12:13 编辑

int *p, i, j, k;

for (i=1; i<=8; i++)
{
        p = A;
        k = i;
        for (j = 0; j<i; j++)
       {
              *p++ = k;
              k -- ;
       }
}

更简单的直接初始化A[8] = {8,7,6,5,4,3,2,1}, 然后根据下标去使用数组,比如对第一次输入, 取A[7] = 1; 第二次输入, 取A[6] = 2, A[7] = 1,..., 稍稍变换一下就可以了,没有数据的移动。

使用特权

评论回复
17
nayaix| | 2010-5-12 11:03 | 只看该作者
顶7楼的

使用特权

评论回复
18
冷漠| | 2010-5-12 12:46 | 只看该作者
本帖最后由 冷漠 于 2010-5-12 12:55 编辑

先顶13楼mohanwei的。
再化简6楼的,化到最简,让人看得懂:
void main( )
{
unsigned char A[8];
char i,aa=1;
A[0]=1;
while( (aa++) && (aa<8) )
{
     for( i=aa; i>0; i--)   A[ i ]=A[ i-1] ;
       A[0]=A[0]+1;
  }
while(1);
}

使用特权

评论回复
19
zhzy724| | 2010-5-12 13:02 | 只看该作者
/***************   writer:shopping.w   ******************/
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code FFW[]=          //正转
{
        0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09  
};

uchar code REV[]=        //反转
{
        0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01
};

sbit K1 = P3^0;
sbit K2 = P3^1;
sbit K3 = P3^2;

void DelayMS(uint ms)  //延时
{
        uchar i;
        while(ms--)
        {
                 for(i=0;i<120;i++);
        }
}

void SETP_MOTOR_FFW(uchar n)   //正转
{
        uchar i,j;
        for(i=0;i<1*n;i++)
        {
                 for(j=0;j<8;j++)
                {
                         if(K3 == 0)        break;
                        P1 = FFW[j];
                        DelayMS(25);
                }
        }
}

void SETP_MOTOR_REV(uchar n)  //反转
{
        uchar i,j;
        for(i=0;i<1*n;i++)
        {
                 for(j=0;j<8;j++)
                {
                         if(K3 == 0)        break;
                        P1 = REV[j];
                        DelayMS(25);
                }
        }
}

void main()
{
        uchar N = 1;
        while(1)
        {
                 if(K1 == 0)
                {  while(K1==0);
                         P0 = 0xfe; //正转LED指示
                        SETP_MOTOR_FFW(N);
                        if(K3 == 0) break;
                }
                else if(K2 == 0)
                {        while(K2==0);
                         P0 = 0xfd;        //反转LED指示
                        SETP_MOTOR_REV(N);
                        if(K3 == 0) break;
                }
                else
                {
                         P0 = 0xfb;          //停LED指示
                        P1 = 0x03;
                }
        }
}
当按下K1(K2)时怎么每次都正转72°(反转72°)?
程序怎么改让它只转9°?
请各位大侠帮忙

使用特权

评论回复
20
colinluan| | 2010-5-12 14:42 | 只看该作者
建议楼主看下数据结构里的循环队列。时间复杂度为1.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:QQ:847991464

49

主题

188

帖子

0

粉丝