對於線性表的操做過程,須要對指針操做這一塊比較熟悉,由於算法中用到的指針很是多,包括順序表和鏈表的建表,LinkList *L都是不少題目須要用到的結構,定義結構體等等操做仍是須要多熟悉。同時,不一樣狀況對於順序表和鏈表的選擇也是不同的,順序表的特色在於無需爲表示結點間的邏輯關係而增長額外的存儲空間,存儲利用率提升,而且能夠方便的存儲表中的任一結點,存儲速度快。而鏈表的特色在於能夠方便的進行擴充而且能夠方便的刪除和插入。因此不少時候考慮一個算法的效率或者功能,也是在於對順序表和鏈表的選擇。對於線性表這一塊,c++語法也不少的應用到,cin和cout,new等語句都大大簡化代碼長度,可讀性也更強,因此線性表仍是須要好好下功夫學習。c++
6-4 順序表操做集 (20 分)
本題要求實現順序表的操做集。
各個操做函數的定義爲:
List MakeEmpty():建立並返回一個空的線性表;
Position Find( List L, ElementType X ):返回線性表中X的位置。若找不到則返回ERROR;
bool Insert( List L, ElementType X, Position P ):將X插入在位置P並返回true。若空間已滿,則打印「FULL」並返回false;若是參數P指向非法位置,則打印「ILLEGAL POSITION」並返回false;
bool Delete( List L, Position P ):將位置P的元素刪除並返回true。若參數P指向非法位置,則打印「POSITION P EMPTY」(其中P是參數值)並返回false。算法
List MakeEmpty()函數建立空線性表
a=new LNode
a->last=NULL尾節點爲空,建立成功返回線性表
Position Find( List L, ElementType X )函數找出函數中特定元素
if(!L)先判斷是否爲空
for i=0 to L->last遍歷鏈表
if(L->date[i]==X)判斷是不是要找到的數
return i若是是要找的數,返回當前的節點
bool Insert( List L, ElementType X, Position P )函數插入節點
兩個if語句判斷是否爲滿和是否非法區域
for i=L->last to P從表尾遍歷至須要的位置
L->Data[P]=X;++L->Last;讓p節點爲X,最大長度節點後移
bool Delete( List L, Position P )函數刪除指定節點元素
if(P>=L->last||P<0)判斷是否越界,最大長度節點前移
for i=P to L->last從P節點開始後面的元素前移數組
·Q1:這道題是我作完後面的題目以後再回來作的,因此函數的實現基本沒什麼問題,編譯錯誤的緣由是有幾個判斷條件,好比說刪除和插入函數中的判斷空沒有加下去,並且把主函數都寫進去了
·A1:後來對照着同窗的代碼修改了一下,加上了兩個判斷,而且細節處也作了優化,如++L->last和--L->last都是同窗給的建議。數據結構
6-9 jmu-ds-有序鏈表合併 (20 分)函數
已知兩個遞增鏈表序列L1與L2,2個鏈表都是帶頭結點鏈表。設計函數實現L1,L2的合併,合併的鏈表仍然遞增有序,頭結點爲L1的頭結點。 合併後須要去除重複元素。
輸入格式: 輸入分兩行,先輸入數據項個數,再輸入數據項,數字用空格間隔。
輸出格式: 在一行中輸出合併後新的遞增鏈表,數字間用空格分開,結尾不能有多餘空格;學習
LinkList pa=L1->next,pb=L2->next,r,s; 定義指針,r指針和s指針分別表明L1的操做指針和新鏈表的操做指針
while(pa!=NULL&&pb!=NULL)循環進行的條件,讓指針的指向不會跑到非法區域
if的三個判斷,兩個鏈表的元素大小關係執行相應操做,目的是有序的整合到一個數組中去
接下來的兩個while(pa,pb!=NULL)則是讓新的鏈表繼承本來兩個鏈表的全部數據而且保持有序
r->next=NULL的做用是讓r鏈表不溢出測試
·Q1:第一次沒有加入當兩個表的元素相同的時候的判斷條件,致使了第一個測試點錯誤。
`A1:在判斷兩個表元素大小以後加入判斷元素是否相同函數
·Q2:加入判斷以後,測試點仍是錯誤,發現判斷相同函數不能在判斷大小函數以後
·A2:把判斷相同函數加入到判斷相等函數以前
·Q3:指針的做用重疊,致使內存發生錯誤
·A3:從新定義指針,多了兩個指向next的指針優化
6-10 jmu-ds-有序鏈表的插入刪除 (15 分)編碼
鏈表L是一個有序的帶頭結點鏈表,實現有序鏈表插入刪除操做。實現函數爲:
函數接口定義:
void ListInsert(LinkList &L,ElemType e);//有序鏈表插入元素e
void ListDelete(LinkList &L,ElemType e);//鏈表刪除元素e設計
void ListInsert(LinkList &L,ElemType e)函數實現插入元素e
LinkList s,p定義指針指向L和新鏈表
動態分配內存以後開始while循環遍歷鏈表
if(p->next==NULL)當p指向最後一個數,即插入元素位置爲最後一個
if(p->data>e)插入點不爲最後一個,找到插入點,以後的元素後移
void ListDelete(LinkList &L,ElemType e)函數實現刪除指定元素
一樣LinkList s,p定義指針指向L和新鏈表
while循環遍歷鏈表,if(p->data==e)找到相應元素
開始刪除操做
·Q1:第一次出現錯誤是編譯錯誤,加入了一個沒有的變量n做爲鏈表長度
·A1:刪除n,從新安排循環
·Q2:第二次出現的錯誤直接是段錯誤,沒有定義鏈表末尾,內存溢出
·A2:按找同窗給的建議修改了一下,在刪除函數中加入判斷
約瑟夫環問題:一圈共有N我的,開始報數,報到M的人自殺,而後從新開始報數,問最後自殺的人是誰?
圓桌問題
模擬整個過程,複雜度爲O(NM)。能夠用數學方法來求解: 把問題從新描述一下:N我的(編號0~(N-1)),從0開始報數,報到(M-1)的自殺,剩下的人繼續從0開始報數。求最後自殺者的編號。第一個自殺的人是(M-1)%N,例如上圖中,41我的中,報到3的人自殺,則字一個自殺的人的編號是(3-1)%41=2。有人自殺後,下一個位置M又從零開始報數,問題變爲(N-1)我的,報到爲(M-1)的人自殺,問題規模減少了。定義F(N-1)爲總數爲N-1我的時,最後自殺的人的序號。根據上面的對比,F(N-1)能夠當作是N我的自殺掉一個以後從新編碼組成的新問題,與從新編碼以前的序號對比多了一個M,那麼F(N-1) + M就至關因而N我的自殺掉一個以後,接着繼續自殺到最後一個的序號。
這道題的規則看起來很簡答,就是循環報數,而後逐一剔除人員,剩下最後的一個。可是實際的思路卻比較複雜,首先要實現循環報數就須要用到循環鏈表,而後重複遍歷鏈表,而且重複刪除數據,移動節點,操做起來就相對複雜一些,剛開始系看到這道題,想的是能不能用數組寫一寫看看,可是後面的定義內存太大了,主要是不知道題目的定義大小,而後就得把空間定義的很大,這樣對於時間複雜度和空間複雜度都不利。以後看了用數學的方法轉化成數據結構的方法來解答,大大節省了空間和時間。因此說鏈表作法不少時候都是更加便利。之後要多學着用鏈表和線性表來解答題目了