线性表(一)——数组循环右移算法

源码:rshift.cpp

#include "stdafx.h"
#include <stdio.h>

/************************************************************************/
/* 数组循环右移算法                                                     */
/************************************************************************/

/*
 * 要求:只用一个元素大小的辅助空间,且时间复杂度为O(n)
 */

//************************************
// Method:    求最大公约数(辗转相除)
// FullName:  gcd
// Access:    public
// Returns:   int
// Qualifier:
// Parameter: int m
// Parameter: int n
//************************************
int gcd(int m, int n)
{
    return n ? gcd(n, m % n) : m;
}

//************************************
// Method:    循环右移解法一(通俗解法)
// FullName:  rshift1
// Access:    public
// Returns:   void
// Qualifier:
// Parameter: int array[]
// Parameter: int length
// Parameter: int shift
//************************************
void rshift1(int array[], int length, int shift)
{
    //求最少循环移动链的数量
    //设length=m,shift=n
    //则[0] -> [n%m] -> [2n%m] -> ... -> [mn%m]=[0]=起始
    //假设kn%m==0,令m=gcd*X,n=gcd*Y,则X与Y互斥
    //则k*Y%X==0,Y与X互斥,故X能整除k,故k=m/gcd
    //k是一条链条的长度,故链条的数量为m/k=gcd
    int least_movement = gcd(length, shift);//最少循环移动链的数量
    int i;
    for (i = 0; i < least_movement; i++)
    {
        int swap_a = i;
        int swap_b = (i + shift) % length;
        int tmp = array[swap_a];
        while (swap_b != i)
        {
            array[swap_a] = array[swap_b];
            swap_a = swap_b;
            swap_b = (swap_b + shift) % length;
        }
        array[swap_a] = tmp;
    }
}

//************************************
// Method:    循环右移解法二(翻转解法)
// FullName:  rshift2
// Access:    public
// Returns:   void
// Qualifier:
// Parameter: int array[]
// Parameter: int length
// Parameter: int shift
//************************************
void rshift2(int array[], int length, int shift)
{
    //翻手掌算法
    //设length=m,shift=n(n=n%m)
    //方法:分割数组 => array1[0 .. n-1] | array2[ n .. m-1 ]
    //array1翻转,array2翻转,再整体翻转
    //
    //原先:     1,2,3,4,..,n-1     | n,...,m-2,m-1
    //各自翻转: n-1,n-2,...,2,1    | m-1,m-2,...,n
    //全部翻转: n,n+1,...,m-2,m-1  | 1,2,3,...,n-2,n-1
    //这就完成了右移n单位的任务
    int i;
    shift %= length;
    int tmp;
    for (i = 0; i < (shift - 1) / 2; i++)
    {
        tmp = array[i];
        array[i] = array[shift - i - 1];
        array[shift - i - 1] = tmp;
    }
    for (i = shift; i < shift + (length - shift) / 2; i++)
    {
        tmp = array[i];
        array[i] = array[length + shift - i - 1];
        array[length + shift - i - 1] = tmp;
    }
    for (i = 0; i < length / 2; i++)
    {
        tmp = array[i];
        array[i] = array[length - i - 1];
        array[length - i - 1] = tmp;
    }
}

void print_array(int array[], int length)
{
    int i;
    for (i = 0; i < length; i++)
    {
        printf("%d ", array[i]);
    }
    printf("\n");
}

int main(int argc, char* argv[])
{
    int a[] = { 1,2,3,4,5,6 };
    printf("=====================\n");
    print_array(a, 6);
    printf("========== rshift ==========\n");
    rshift1(a, 6, 3);
    print_array(a, 6);
    printf("========== rshift ==========\n");
    rshift2(a, 6, 3);
    print_array(a, 6);
    return 0;
}
时间: 2024-11-06 16:57:49

线性表(一)——数组循环右移算法的相关文章

(转)数组循环右移

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加变量. 不合题意的解法如下: 我们先试验简单的办法,可以每次将数组中的元素右移一位,循环K次.abcd1234→4abcd123→34abcd12→234abcd1→1234abcd.伪代码如下: 代码清单2-33 RightShift(int* arr, int N, int K) { while(K--) { int t = arr[N - 1]; for(int i = N - 1; i >

数组循环右移问题

首先,假设我们有一个具有6个元素的数组: 1,2,3,4,5,6 现在我们要对这个数组循环右移4次,我们很直接很够推出它的结果是:3,4,5,6,1,2 .但是我们如何去实现这样一个问题呢? 我觉得大家最容易想到的方法就是: step1:保存好数组中最后一个元素的值 step2:从第一个元素到倒数第二个元素依次向右移动一个位置 step3:然后将刚保存的值放到空出来的数组第一个位置 虽然这个方法想起来很简单,但是它的效率却不是很高,它的时间复杂度是O(n^2). 现在,我再介绍一种效率较高的算法

数组循环右移

Q:把一个含有 N 个元素的数组循环右移 K 位,要求时间复杂度为 O (N),且只允许使用两个附加变量. 开始的思路: 1.若k=整数倍N, 完成:k大于N,k=N%k:k小于N,开始处理. 2.tmp1保存取出的元素a[k]:a[0]放在k:tmp2保存a[2k], tmp1放入2k:tmp1保存a[3k],tmp2放入3k...直到位置[0]被放入一个新值,一轮循环完毕.这是一个从位置[0]出发,又回到位置[0]的接龙游戏. 仔细考虑下,发现,若N%k==0,则需要从[0]开始,[0]结束

线性表之数组描述

1.线性表的描述可以分为两种 数组描述:StaticList和DynamicList(动态数组) 链式描述 2.数组描述 数组描述方法将元素存储在一个数组中,通过一个索引以确定每个元素存储的位置 所有元素依次存储在一片连续的存储空间中 线性表中的每一个元素对应数组中的一个位置 3.创建一个数组类 要创建一个数组类必须确定数组类型和确定数组长度,所以针对以上两个问题有以下解决: 模板类 动态数组(数组空间不够的情况下动态增加数组长度) 4. StaticList类实现 使用原生数组作为顺序存储空间

第2章 线性表《C#数据结构和算法》

( 1)除第一个位置的数据 元素外,其它数据元素位置的前面都只有一个数据元素:( 2)除最后一个位置的 数据元素外,其它数据元素位置的后面都只有一个元素.也就是说,数据元素是 一个接一个的排列.因此,可以把线性表想象为一种数据元素序列的数据结构. 2.1.1 线性表的定义 线性表(List) 线性表的接口如下所示. public interface IListDS<T> { int GetLength(); //求长度 void Clear(); //清空操作 bool IsEmpty();

数据结构线性表的动态分配顺序存储结构算法c语言具体实现和算法时间复杂度分析

#include<stdio.h>#include<stdlib.h>//线性表的动态分配顺序存储结构#define LIST_INIT_SIZE 100//线性表存储空间的初始分配量#define LISTINCREMENT 10//线性表存储空间的分配增量//函数结果状态代码#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2typedef

习题8-3 数组循环右移(20 分)

本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a?0??a?1???a?n?1??)变换为(a?n?m???a?n?1??a?0??a?1???a?n?m?1??)(最后m个数循环移至最前面的m个位置). 函数接口定义: int ArrayShift( int a[], int n, int m ); 其中a[]是用户传入的数组:n是数组的大小:m是右移的位数.函数ArrayShift须将循环右移后的数组仍

PAT 1008(数组循环右移问题)

1008 数组元素循环右移问题 (20分) 一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A?0??A?1???A?N−1??)变换为(A?N−M???A?N−1??A?0??A?1???A?N−M−1??)(最后M个数循环移至最前面的M个位置).如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法? 输入格式: 每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0):第2行输入N个整数,之间用空格分隔

算法习题---线性表之数组实现循环移动

一:问题 设将n(n>1)个整数存放到一维数组R中,试设计一个在时间和空间两方面都尽可能高效的算法,将R中保存的序列循环左移p(0<p<n)个位置,即把R中的数据序列由(x0,x1,…,xn-1)变换为(xp,xp+1,…,xn-1,x0,x1,…,x). 二:思考 要实现R中序列循环左移P个位置,只需先将R中前P个元素逆置,再将剩下的元素逆置,最后将R中所有的元素再整体做一次逆置操作即可,本题算法描述如下: (一)步骤一:将前P个元素逆置 (二)步骤二:将后P个元素逆置 (三)步骤三: