線性表之順序表操作(已完結)
阿新 • • 發佈:2018-12-25
考研408資料結構線性表複習;
有任何問題私我
#include<iostream> #include<algorithm> const int initlength = 100; ///順序表的初始長度 using namespace std; typedef struct { int *data; int MaxSize, length; ///順序表的最大儲存空間,長度; }SeqList; ///*****順序表基本操作 void initList(SeqList &L, int n = initlength) ///初始化順序表 { L.data = new int [n]; L.length = 0; L.MaxSize = n; for(int i=0;i<L.MaxSize;++i) { cin>>L.data[i]; L.length++; } } int Length(SeqList L) ///返回順序表的長度 { return L.length; } bool EmptyList(SeqList L) ///判斷順序表是否為空 { if(L.length == 0) return true; return false; } bool ListInsert(SeqList &L, int i, int value) ///插入元素, i為元素的位置, value為元素的值 { if(i<1 || i>L.length+1) return false; if(i >= L.MaxSize) return false; for(int j=L.length; j>=i; --j) L.data[j] = L.data[j-1]; L.data[i-1] = value; L.length++; return true; } bool ListDelete(SeqList &L, int i, int &e) ///刪除元素, i為刪除元素的位置, e為刪除位置元素的值 { if(i<1 || i>L.length) return false; e = L.data[i-1]; for(int j=i-1; j<L.length-1; ++j) L.data[j] = L.data[j+1]; L.length--; return true; } int LocateElem(SeqList L, int e) ///按值查詢第一個元素值為e的位序 { for(int i=0; i<L.length; ++i) { if(e == L.data[i]) return i+1; } return 0; } void PrintList(SeqList L) ///列印輸出整個順序表 { for(int i=0;i<L.length;++i) cout<<L.data[i]<<" "; cout<<endl; } ///***順序表進階操作,帶題目描述 ///1.在順序表中刪除具有最小值的元素(假設唯一), 並由函式返回被刪元素的值 /// 空出的位置由最後一個元素填補。若順序表為空,顯示錯誤資訊並退出 bool DeleteMinList(SeqList &L, int &e) { if(EmptyList(L)) //if (L.length == 0) { cout<<"The List is empty, can't delete the min value!"<<endl; return false; } int ListMin = L.data[0]; int LocalMin = 0; for(int i=0;i<L.length;++i) { if(ListMin > L.data[i]) { ListMin = L.data[i]; LocalMin = i; } } e = ListMin; L.data[LocalMin] = L.data[L.length-1]; L.length--; return true; } ///2.設計一個高效演算法,將順序表的所有元素逆置,要求演算法的空間複雜度為O(1) void ReverseList(SeqList &L) { int temp; for(int i=0;i<L.length/2;++i) { temp = L.data[i]; L.data[i] = L.data[L.length-i-1]; L.data[L.length-i-1] = temp; } } ///3.長度為n的順序表L, 編寫一個時間複雜度為O(n), 空間複雜度為O(1), 該演算法刪除線性表中所有值為x的資料元素。 ///可為該順序表重新構造 void DeleteEqualElement(SeqList &L, int x) { int k = 0; for(int i=0; i<L.length; ++i) { if(L.data[i] != x) { L.data[k] = L.data[i]; k++; } } L.length = k; } ///或者第二種演算法 /* void DeleteEqualElement(SeqList &L, int x) { int k=0, i=0; while(i<L.length) { if(L.data[i] == x) k++; else L.data[i-k] = L.data[i]; i++; } L.length -= k; } */ ///4.從有序順序表中刪除其值在給定值s與t之間(要求s<t)的所有元素,如果s或t不合理或者順序表為空則顯示出錯資訊並退出執行。 /* bool Delete_s_among_t(SeqList &L, int s, int t) ///呼叫此函式前請使用sort或者自定義演算法對順序表排序,使之成為有序表 { if(s>=t || EmptyList(L)) { cout<<"The function is not exploit,please check your input or if the list is empty."; return false; } int k=0; int num=0; for(int i=0;i<L.length;++i) { if(L.data[i] > s && L.data[i] < t) { num++; if(num == 1) k = i; } } if(num == 0) return false; for(int i=k;i<L.length-num;++i) { L.data[i] = L.data[i+num]; } L.length -= num; return true; } */ ///王道給出標準演算法 bool Delete_s_among_t(SeqList &L, int s, int t) { if(s>=t || EmptyList(L)) { return false; } int i, j; for(i=0; i<L.length&&L.data[i]<s; i++) if(i >= L.length) return false; for(j=i; j<L.length&&L.data[j]<=t; j++){} for(;j<L.length; i++, j++) L.data[i] = L.data[j]; L.length = i+1; return true; } ///5.從順序表中刪除其值在給定值s與t之間(包含s和t, 要求s<t)的所有元素,如果s或t不合理或者順序表為空則顯示錯誤資訊並退出執行。 /* bool Delete_s_among_t2(SeqList &L, int s, int t) { if(s>=t || EmptyList(L)) { cout<<"The function is not exploit,please check your input or if the list is empty."<<endl; return false; } bool flag = false; for(int i=0;i<L.length;++i) { if(L.data[i]>=s && L.data[i] <= t) { for(int j=i;j<L.length-1;++j) L.data[j] = L.data[j+1]; L.length--; flag = true; --i; } } return flag; } */ ///王道推薦高效演算法 bool Delete_s_among_t2(SeqList &L, int s, int t) { if(s>=t || EmptyList(L)) { return false; } int k = 0; for(int i=0;i<L.length;++i) { if(L.data[i] >= s && L.data[i] <= t) k++; else L.data[i-k] = L.data[i]; } L.length -= k; return true; } ///6.從有序順序表中刪除所有其值重複的元素,使表中所有元素的值均不同 bool Delete_repeat_value(SeqList &L) { if(EmptyList(L)) return false; int i, j; for(i=0, j=1;j<L.length;++j) { if(L.data[i]!=L.data[j]) L.data[++i] = L.data[j]; } L.length = i+1; return true; } ///7.將兩個有序順序表合併成一個有序順序表,並由函式返回結果順序表。 SeqList combine_List(SeqList L1, SeqList L2, SeqList &L3) { ///加層判斷,若L3最大儲存空間小於L1+L2的長度,則返回 int i=0, j=0, k=0; while(i<L1.length && j<L2.length) { if(L1.data[i] < L2.data[j]) { L3.data[k++] = L1.data[i++]; } else { L3.data[k++] = L2.data[j++]; } } while(i<L1.length) L3.data[k++] = L1.data[i++]; while(j<L2.length) L3.data[k++] = L2.data[j++]; L3.length = k; return L3; } ///8.已知在一維陣列A[m+n]中依次存放著兩個線性表,試編寫一個函式,將陣列中兩個順序表的位置互換,即將bn放在an前面 void reverse_list(SeqList &L, int n) { int mid = (L.length)/2; for(int i=0;i<mid;++i) { int t = L.data[i]; L.data[i] = L.data[L.length-i-1]; L.data[L.length-i-1] = t; } mid = (L.length-n)/2; for(int i=0; i<mid; ++i) { int t = L.data[i]; L.data[i] = L.data[L.length-n-i-1]; L.data[L.length-n-i-1] = t; } mid = n/2; for(int i=0; i<n/2; ++i) { int t = L.data[L.length-n+i]; L.data[L.length-n+i] = L.data[L.length-i-1]; L.data[L.length-i-1] = t; } } ///王道推薦演算法,由兩個函式構成 個人略微調整了一下 void Reverse_list(SeqList &L, int left, int right) ///該函式用於進行逆置 { if(left >= right || right >= L.length) return; int mid = (left + right)/2; for(int i=0;i<=mid-left;++i) { int t = L.data[left + i]; L.data[left+i] = L.data[right-i]; L.data[right-i] = t; } //PrintList(L); } void Exchange(SeqList &L, int n) { Reverse_list(L, 0, L.length-1); Reverse_list(L, 0, L.length-n-1); Reverse_list(L, L.length-n, L.length-1); } ///9.線性表中元素遞增有序且按照順序儲存於計算機內,要求設計一演算法完成用最少時間在表中查詢數值為x的元素, ///若找到後將其與後繼元素位置相交換,若找不到則將其插入表中並使表中元素仍遞增有序。 void mid_find(SeqList &L, int l, int r, int key) ///查詢演算法採取二分 { if(l >= r) return; int mid; while(l<=r) { mid = (l + r)/2; if(L.data[mid] == key) break; ///進行交換操作 else if(L.data[mid] > key) r = mid - 1; else l = mid + 1; } //cout<<mid<<endl; //cout<<l<<" "<<r<<endl; if(L.data[mid] == key && mid != L.length-1) { int t = L.data[mid+1]; L.data[mid+1] = L.data[mid]; L.data[mid] = t; } if(l>r) { for(int i=L.length;i>l;--i) L.data[i] = L.data[i-1]; L.data[l] = key; L.length++; } } ///10.設將n個證書存放在一維陣列R中,試實際一個在時間和空間兩方面都儘可能高效的演算法。 ///將R中儲存的序列迴圈左移p個位置,即將R中的資料由(X0, X1, ...Xn-1)變換為(Xp, Xp+1, ....Xn-1, X0, X1..., Xp-1) ///與8題相同思路 ///11.一個長度為L的升序序列S, 處在第[L/2]個位置的數稱為S的中位數。現在有兩個等長序列A和B, ///試設計一個時間和空間都儘可能高效的演算法,找出兩個序列A和B的中位數 ///演算法描述:分別求兩序列的中位數a和b。 ///1.若a=b, 則結束,a或b即為所求中位數 ///2.若a<b, 則捨棄A中較小一半,同時捨棄B中較大一半, 要求兩次捨棄長度相等 ///3.若a>b, 則捨棄A中較大一半,同時捨棄B中較小一半, 要求兩次捨棄長度相等 ///在保留的兩個升序序列中,重複過程123, 知直到兩個序列中只含一個元素為止, 較小者即為所求中位數 int M_search(SeqList &L1, SeqList &L2) { int s1=0, d1=L1.length-1, m1, s2=0, d2=L2.length-1, m2; while(s1!=d1 || s2!=d2) { m1 = (s1+d1)/2; m2 = (s2+d2)/2; if(L1.data[m1] == L2.data[m2]) return L1.data[m1]; else if(L1.data[m1] > L2.data[m2]) { if((s1+d1)%2 == 0) { d1 = m1; s2 = m2; } else { d1 = m1; s2 = m2+1; } } else { if((s1+d1)%2 == 0) { s1 = m1; d2 = m2; } else { s1 = m1 + 1; d2 = m2; } } } return L1.data[s1]>L2.data[s2]? L2.data[s2]:L1.data[s1]; } ///12.已知一個整數序列,若存在m個相同元素(m>n/2),則稱m為A中的主元素,若存在主元素,輸出,不存在,輸出-1 ///王道推薦演算法(本人首先想到雜湊演算法) ///查找出現次數最多的元素為難點 int Majority(SeqList &L)///查詢可疑出現次數最多元素演算法??? { int c=L.data[0], num =1; for(int i=1;i<L.length;++i) { if(L.data[i] == c) num++; else if(num > 0) num--; else { c = L.data[i]; num = 1; } } num = 0; for(int i=0;i<L.length;++i) if(c == L.data[i]) num++; if(num > L.length/2) return c; else return -1; } int main() { ios::sync_with_stdio(false); SeqList L; int n; cin>>n; initList(L, n); /* initList(L1, n); cin>>m; initList(L2, m); ListInsert(L, 5, 8); PrintList(L); cout<<"The List Length is "<<Length(L)<<endl; int e; ListDelete(L, 5, e); PrintList(L); cout<<"e's value is "<<e<<endl; cout<<"The List Length is "<<Length(L)<<endl; int order = LocateElem(L, 6); if(order != 0) cout<<"The element's order is "<<order<<endl; else cout<<"sorry, we can't find the value's order!!!"<<endl; DeleteMinList(L, e); PrintList(L); cout<<"e's value is "<<e<<endl; ReverseList(L); PrintList(L); Delete_s_among_t2(L, 6, 9); PrintList(L); L3 = combine_List(L1, L2, L3); PrintList(L3); cout<<L3.length<<endl; //reverse_list(L3, 2); Exchange(L3, 2); PrintList(L3); mid_find(L, 0, L.length-1, 5); PrintList(L); cout<<M_search(L1, L2)<<endl;*/ cout<<Majority(L)<<endl; return 0; }