2012-01-12 65 views
4

是否可以在一個數組內存儲一組滾動的值而不超出設定的索引?在固定大小的數組內存儲「N」個記錄

比如我把一個基本的控制檯例如方式如下:

static void Main(string[] args) 
{ 
    int[] myvalue; 
    myvalue = new int[10]; 

    for (int i = 0; i < 20; i++) 
    { 
     Console.WriteLine("Array {0} is {1}", i, myvalue[i]);   
    } 
    Console.ReadLine(); 

} 

在目前的方案,我得到一個索引越界異常。我想要做的是將數組限制爲10個項目,但隨着計數增加用新值覆蓋現有項目。因此,我可以迭代100次,但數組只會顯示程序結尾的最後十個值(89-99)。

如果數組不是最好的方法,我會歡迎任何有關如何將其存儲在內存中的建議。

謝謝

+0

89-99是11個值:p但是你的意思是?覆蓋現有的項目?顯示lat十?你正在閱讀還是寫入數組? – davogotland 2012-01-12 01:38:30

回答

6

您可以使用List來存儲值,然後包裝Add方法來處理項數的限制。這將爲您處理所有「滑下」邏輯。

const int MAX_ITEMS = 10; 
List<int> list = new List<int>(); 

void AddItem(int k) 
{ 
    list.Add(k); 
    if (list.Count > MAX_ITEMS) 
    { 
     // discard the item at the front of the list 
     list.RemoveAt(0); 
    } 
} 

每當你想添加一個值,你只需要調用AddItem(n),例如:

for (int i = 0; i < 100; i++) 
{ 
    AddItem(i); 
} 

每當你想讀出值,你可以簡單地做:

for (int i = 0; i < list.Count; i++) 
{ 
    Console.WriteLine(list[i]); 
} 

這也有一個好處,就是你可以放入最少數量的物品(比如你只有6個而不是10個),它仍然可以正常工作(你不必擔心空缺數組項目)。

+0

非常感謝Brian – rlcrews 2012-01-12 17:54:17

+0

沒問題;樂意效勞。 – 2012-01-13 01:32:30

3

如果你想數組總是通過複製array[N]array[N-1]所有每次抱過去十年值在他們遇到的順序,那麼你就必須「幻燈片值向下」的數組N> = 1,然後在最後一個位置寫入「最新」值。

如果您不需要該數組具有這個特定順序的值,那麼可以使用模數技巧並將任何i寫入array[i % ARRAYSIZE];這會在你到達結尾時立即「循環」到數組的開頭。

最後,如果想爲了值,你需要一個數據結構,不強迫你在每個迭代中的所有元素複製你可以使用:

  • 一個linked list,如果索引訪問不是要求
  • 雙端隊列(又名雙端隊列),如果您還需要索引訪問 - .NET沒有附帶內置的一個,但有一個行之有效的實施爲PowerCollections
部分
0

你可以嘗試這樣的:

myvalue = new int[10]; 
for (int i = 0; i < 100; i++) 
    myvalue[i % myvalue.Length] = i; 

當然在到達結尾時將從頭開始,所以陣列可能不會在你寫你的價值觀了進去,但有些旋轉的順序。如果您想避免這種情況,則需要將myvalue[1]myvalue[myvalue.Length-1]的元素複製到myvalue[1]myvalue[myvalue.Length-2],並在每次插入新元素時覆蓋myvalue[myvalue.Length-1]。或者,在完成所有插入操作後,您可以旋轉陣列來修復定位。

1

而不是一個數組,你可以使用循環鏈表。

在下面的代碼片段中,currentNode總是輸入的最後一個節點。這種方式隨着鏈表的完整循環,您可以使列表任意長,並且永遠不必擔心結束的位置,因爲在某些時候,您會自動開始覆蓋舊值。

static void Main(string[] args) 
{ 
    //create first node 
    var firstNode = new Node(); 
    var lastNode = firstNode; 

    //create linked list 
    for(int i=0; i<9; i++) 
    { 
     var nextNode = new Node(); 
     lastNode.nextNode = nextNode; 
     lastNode = nextNode; 
    } 

    //link tail of list to beginning to make the circular reference. 
    lastNode.nextNode = firstNode; 

    var currentNode = firstNode; 

    //your code goes here 
    for(int j=0; j<1000; j++) 
    { 
     currentNode.value = j; //now you set your values in your loop 
     currentNode = currentNode.nextNode; //and move on to the next node 
    } 
} 

public class Node 
{ 
    public int value; 
    public Node nextNode; 
} 
0

這可能不是最優雅的代碼以往,但它說明了如何使記錄N個最近的值的循環緩衝區:

const int SIZE = 10; 
int[] myValue = new int[SIZE]; 
int start = 0; 
int count = 0; 

void NewValue(int v) 
{ 
    myValue[start] = v; 
    if (count < SIZE) 
     count++; 
    start = (++start) % SIZE; 
} 

void ListValues() 
{ 
    for (int i = start - 1; i >= 0; i--) 
     Console.WriteLine(myValue[i]); 
    if (count >= SIZE) 
     for (int i = SIZE - 1; i >= start; i--) 
      Console.WriteLine(myValue[i]); 
    Console.WriteLine(); 
} 

private void Test() 
{ 
    for (int i = 0; i < 20; i++) 
    { 
     NewValue(i); 
     ListValues(); 
    } 
}