1. 程式人生 > >【資料結構與演算法】線性表——刪除重複元素

【資料結構與演算法】線性表——刪除重複元素

線性表是一種隨機存取的結構,和連結串列不同,連結串列順序存取的結構。但是,線性表是一種順序儲存的結構,而連結串列是鏈式儲存結構。兩者都是線性的,但區別不同。

 

進入主題:

1.假如有一串資料元素,要求刪除其中的重複元素。

首先想到的是用兩層迴圈,第一層從第一個元素開始,第二層從第一層元素的下一個元素開始。

就是假如第一層是ai元素,則第二層就為ai+1元素。

函式實現:

void Purge1(ElemType A[],int &n){//ElemType表示任意資料型別,以後不再說明//n為線性表的長度
    int i=0,j;
    while(i<n){
    j=i+1;
    while(j<n){
      if(A[j]==A[i])
        Deletelist(A,n,j+1);//具體函式實現最後給出
      else
        j++;
    }
    i++;
  }
}

2.如果這些元素是按遞增排列,且資料量很大的話,使用上面的演算法就會造成時間上的浪費。

那要怎麼優化呢?

具體想法就是用一個變數k記錄重複的個數,然後第i個元素和第i+1個元素進行比較,若相等,則k自增。否則第i+1個元素的值賦值給第i-k+1個元素的值。當k=0時,其實就是自己賦值給自己。

舉個例子:

1  2  2  3  4  6  6  6  8  9

i從第1個元素開始,到第2個元素時,此時第2個元素和第3個元素相等,執行k++。然後進行下一次迴圈,第3個元素不等於第4個元素,因為此時k=1,故第3個元素被賦予第4個元素的值3。然後直到第6個元素,此時又相等,k=2。第7個也相等,k=3。然後到第8個元素,第6個元素被賦予值8,就是第9個元素的值。然後最後一個元素9。此時表的長度為n=10-k=7。 

函式實現:

void Purge2(int *A, int &n) {
  int i = 0, k = 0;//k是重複的次數或是要刪除的數的個數
  for (i = 0; i < n - 1; i++)
    if (A[i] != A[i + 1])
      A[i-k+1] = A[i + 1];
    else
      k++;
  n = n - k;
}

經過小規模的測試沒有發現問題。

 

經過兩函式的分析,可以看出第一個函式使用的是兩層迴圈,而第二個函式只使用了一層迴圈達到了效果。

避免了不必要的時間浪費。

 

附上Deletelist函式:

void Deletelist(int *A, int &n, int i) {
  int j;
  if (i<1 || i>n)//這條可以無視
    cout << "超出範圍!";
  for (j = i; j < n; j++)
    A[j - 1] = A[j];
  n--;
}

溜了,溜了。。。