題目(1):有序鍊錶的合併
將2個遞增的有序鍊錶合併為⼀乙個鍊錶的有序鍊錶; 要求結果鍊錶仍然使⽤用兩個鍊錶的儲存空間,不不另外佔⽤用其他的儲存空間. 表中不不允許有重複的資料。
演算法思想:
(1)假設待合併的鍊錶為la和lb,合併後的新錶使用頭指標lc(lc的表頭結點設為la的表頭結點)指向. pa 和 pb 分別是la,lb的工作指標.初始化為相應鍊錶的首元結點
(2)從首元結點開始比較, 當兩個鍊錶la 和lb 均未到達表尾結點時,依次摘取其中較小值重新鍊錶在lc表的最後.
(3)如果兩個表中的元素相等,只摘取la表中的元素,刪除lb表中的元素,這樣確保合併後表中無重複的元素;
(4)當乙個表達到表尾結點為空時,非空表的剩餘元素直接鏈結在lc表最後.
(5)最後釋放鍊錶lb的頭結點;
void
mergelist
(linklist *la, linklist *lb, linklist *lc)
else
if(pa->data > pb->data)
else
}//將非空表的剩餘元素之間鏈結在lc表的最後
pc->next = pa?pa:pb;
//釋放lb的頭結點
free
(*lb)
;}
題目(2):兩個鍊錶的交集
已知兩個鍊錶a和b分別表示兩個集合.其元素遞增排列列. 設計⼀乙個演算法,⽤用於求出a與b的交集,並
儲存在a鍊錶中; 例例如 : la = ; lb = ; lc = 。
演算法思想:
(1)假設待合併的鍊錶為la和lb,合併後的新錶使用頭指標lc(lc的表頭結點設為la的表頭結點)指向. pa 和 pb 分別是la,lb的工作指標.初始化為相應鍊錶的首元結點
(2)從首元結點開始比較, 當兩個鍊錶la 和lb 均未到達表尾結點時.
(3)如果兩個表中的元素相等,只摘取la表中的元素,刪除lb表中的元素;
(4)如果其中乙個表中的元素較小,刪除此表中較小的元素. 此表的工作指標後移;
(5)當鍊表la和lb有乙個先到達表尾結點為空時,依次刪除另乙個非空表中的所有元素,最後釋放鍊錶lb;
void
intersection
(linklist *la, linklist *lb, linklist *lc)
else
if(pa->data < pb->data)
else
}//lb為空,刪除非空表la中的所有元素
while
(pa)
//la為空,刪除非空表lb中的所有元素
while
(pb)
pc->next =
null
;free
(*lb)
;}
題目(3):鍊錶「原地旋轉」
設計⼀乙個演算法,將鍊錶中所有節點的鏈結⽅方向"原地旋轉",即要求僅僅利利⽤用原表的儲存空間. 換句句
話說,要求演算法空間複雜度為o(1); 例例如:l=, 逆轉後: l = ;
演算法思想:
(1)利用原有的頭結點*l,p為工作指標, 初始時p指向首元結點. 因為摘取的結點依次向前插入,為確保鍊錶尾部為空,初始時將頭結點的指標域置空;
(2)從前向後遍歷鍊錶,依次摘取結點,在摘取結點前需要用指標q記錄後繼結點,以防止鏈結後丟失後繼結點;
(3)將摘取的結點插入到頭結點之後,最後p指向新的待處理節點q(p=q);
void
inverse
(linklist *l)
}
題目(4):刪除鍊錶指定範圍的元素
設計⼀乙個演算法,刪除遞增有序鍊錶中值⼤大於等於mink且⼩小於等於maxk(mink,maxk是給定的兩個
引數,其值可以和表中的元素相同,也可以不不同)的所有元素;
演算法思想:
(1)查詢第乙個值大於mink的結點,用q指向該結點,pre 指向該結點的前驅結點;
(2)繼續向下遍歷鍊錶, 查詢第乙個值大於等於maxk的結點,用p指向該結點;
(3)修改下邊界前驅結點的指標域, 是其指向上邊界(pre->next = p);
(4)依次釋放待刪除結點的空間(介於pre和p之間的所有結點);
void
deleteminmax
(linklist *l,
int mink,
int maxk)
//2.查詢第乙個值大於等於maxk的結點
while
(p && p->data<=maxk)
//3.修改待刪除的結點指標
q = pre->next;
pre->next = p;
while
(q != p)
}
題目(5):鍊錶的指定範圍元素的逆置
設將n(n>1)個整數存放到⼀一維陣列r中, 試設計⼀乙個在時間和空間兩⽅方⾯面都盡可能⾼高效的演算法;將r
中儲存的串行列迴圈左移p個位置(0演算法思路:
先將n個資料原地逆置 9,8,7,6,5,4,3,2,1,0;
將n個資料拆解成[9,8,7,6,5,4,3] [2,1,0]
將前n-p個資料和後p個資料分別原地逆置; [3,4,5,6,7,8,9] [0,1,2]
複雜度分析:
時間複雜度: o(n); 時間複雜度:o(1);
void
reverse
(int
*pre,
int left ,
int right)
}void
leftshift
(int
*pre,
int n,
int p)
}
題目(6):找主元素(攻山頭)
已知⼀乙個整數串行列a = (a0,a1,a2,…an-1),其中(0<= ai <=n),(0<= i<=n). 若存在ap1= ap2 = …=
apm = x,且m>n/2(0<=pk演算法思路:
選取候選主元素, 從前向後依次掃瞄陣列中的每個整數, 假定第乙個整數為主元素,將其儲存在key中,計數為1. 若遇到下乙個整數仍然等於key,則計數加1. 否則計數減1. 當計數減到0時, 將遇到的下乙個整數儲存到key中, 計數重新記為1. 開始新一輪計數. 即可從當前位置開始重上述過程,直到將全部陣列元素掃瞄一遍;
判斷key中的元素是否是真正的主元素, 再次掃瞄陣列, 統計key中元素出現的次數,若大於n/2,則為主元素,否則,序列中不存在主元素;
演算法分析:
時間複雜度: o(n)
空間複雜度: o(1)
int
mainelement
(int
*a,int n)
else
else}}
//如果count >0
if(count >0)
//(6)判斷count>n/2, 確認key是不是主元素
if(count > n/2)
return key;
else
return-1
;//不存在主元素
}
題目(7):刪除絕對值相等的結點,僅保留第乙個
⽤用單鏈表儲存m個整數, 結點的結構為(data,link),且|data|<=n(n為正整數). 現在要去設計⼀乙個時間複雜度盡可能⾼高效的演算法. 對於鍊錶中的data 絕對值相等的結點, 僅保留留第⼀一次出現的結點,⽽而 刪除其餘絕對值相等的結點.例例如,鍊錶a = , 刪除後的鍊錶a=;
演算法思路:
申請大小為n+1的輔助陣列t並賦值初值為0;
從首元結點開始遍歷鍊錶,依次檢查t[|data|]的值, 若[|data|]為0,即結點首次出現,則保留該結點,並置t[|data|] = 1,若t[|data|]不為0,則將該結點從鍊錶中刪除.
複雜度分析:
時間複雜度: o(m),對長度為m的鍊錶進行一趟遍歷,則演算法時間複雜度為o(m);
空間複雜度: o(n)
void
deleteequalnode
(linklist *l,
int n)
//3.指標temp 指向首元結點
linklist temp =
(*l)
->next;
//4.遍歷鍊錶,直到temp = null;
while
(temp!=
null
)else
}}
線性表練習題2
題目要求 長度為n的順序表l,編寫乙個時間複雜度為o n 空間複雜度為o 1 的演算法,該演算法刪除線性表中所有值為x的資料元素。演算法分析 設定兩個計數器,乙個為i,記錄掃瞄過的元素的個數 乙個為j,記錄掃瞄過的非x的元素的個數。從1 n對所有的元素進行掃瞄,如果該元素不是x,則i j 並令i對應...
線性表練習題超詳細解答
天才亦是眾生,眾生皆懷其才。鍊錶練習 1有乙個帶頭結點的單鏈表l,設計乙個演算法使其元素遞增有序。演算法思想 用直接插入排序的方法,將鍊錶分成兩部分,每次取後部分乙個元素插入前部分正確的位置上。void sort linklist l p next pre next 待插元素歸位 pre next ...
線性表演算法題庫 線性表習題
鍊錶。若指標p指向某結點時,能夠根據該指標找到其直接後繼,能夠順後繼指標鏈找到p結點後的結點。但是由於不知道其頭指標,所以無法訪問到p指標指向的結點的直接前趨。因此無法刪去該結點。2.雙鏈表。由於這樣的鍊錶提供雙向指標,根據p結點的前趨指標和後繼指標可以查詢到其直接前趨和直接後繼,從而可以刪除該結點...