什麼是線形表?
答:一種資料結構,簡單的說,n 個資料元素的有限序列。
線性結構的特點:
① 只有乙個首結點和尾結點;
② 除首尾結點外,其他結點只有乙個直接前驅和乙個直接後繼。
線性表順序儲存特點:
① 邏輯上相鄰的資料元素,其物理上也相鄰;
② 若已知表中首元素在儲存器中的位置,則其他元素存放位置亦可求出(利用陣列下標)。
例1 :
乙個一維陣列m,下標的範圍是0到9,每個陣列元素用相鄰的5個位元組儲存。儲存器按位元組編址,設儲存陣列元素 m[ 0]的第乙個位元組的位址是98,則m[ 3] 的第乙個位元組的地是______
解: 位址計算通式為
loc(ai) = loc(a1) + l *
(i-1
)因此:
loc( m[3] ) = 98 + 5 × (3-0) =113
線形表的實現:
定義該資料結構:
#define list_init_size 100 //
初始化分配量,
100
個元素為預設的
線性表的容量
#define listincrement 10 //
線性表儲存空間的分配增量
typedefstructsqlist //
當前線性表分配到的容量
建立乙個線性表:即初始化乙個線性表,構造乙個空的線性表
statusinitlist_sq (sqlist &l)
順序表的插入操作(重要,必須倒背如流)
思路:
① 插入操作應該必須知道些什麼呢?
答:插到哪個線性表,和插到該線性表的什麼位置,還有插的元素,所以該插入函式有三個引數&l , int i ,elemtype e .
② 插入操作中會有什麼可能出現的錯誤呢?
答a: 插入的位置應該是邏輯上成立的1 =< i <= length(l)+1]
b: 如果線性表已經裝滿了,應該分配新的空間
length>=listsize
時候說明滿了
newbase = (elemtype *) realloc (l.elem,
( l.listsize+ listincrement ) *sizeof(elemtype));
③插入後,會對別的元素造成什麼樣的影響?
答如果插入的位置是i ,那麼 從i ->length(l) 都將被移動,共需移動元素n-i+1 很明顯,應該從最右邊的元素下手,依次將i -> n 的元素右移。 p 是指向最後乙個元素的指標,*(p +1)= *p , 最後應該完成掃尾工作++length .
下面寫出原碼 :
voidlist_insert_sq(&l , int i ,elemtype e .)
q = &(l.elem[i-1]); //
插入的位置
for (p = &(l.elem[l.length-1]) ; p>=q; p--) //
依次將i -> n
的元素右移
*p = e ;
++l.length ; }
分析上程式的時間複雜度
最壞的情況下是: 插入的位置是1 ,將移動n-i+1 個元素,插入的位置的概率是 1/n+1, 所以平均演算法時間複雜讀是o(n/2) ;
順序表的刪除操作(重要,必須倒背如流)
思路:
1刪除操作應該必須知道些什麼呢?
答:刪除哪個線性表,和刪除該線性表的什麼位置,返回刪除元素的值,所以該插入函式有三個引數&l , int i ,elemtype e .
2刪除操作會出現什麼可能的錯誤?
3刪除後會對周圍元素造成什麼樣的影響?
答:刪除的位置如果是i ,那麼i+1 到n 的元素都將會左移一位* (p-1 )=*p
很明顯,應該把從線性表的左邊移動,此前把*p 賦給e , 最後掃尾–length
下面給出原碼:
status list_delete_sq (&l , int i ,elemtype e .)
分析上程式的時間複雜度
最壞的情況下是: 刪除的位置是1 ,將移動n-i 個元素,插入的位置的概率是 1/n+1, 所以平均演算法時間複雜讀是o((n-1)/2) ;
關於malloc 與realloc 的理解
首先看一下下面的c 程式片斷:
elemtype malloc(size) // elemtype
指的是資料型別,比如
int
,那就意味著乙個指標指示
4 個位元組
elemtype realloc(
原指標,
size)
,即乙個元素是
4 個位元組。
#include
char *p;
p = (char * ) malloc (10);
p = (char * ) realloc (p,20);
函式首先定義了乙個字元型的指標p ,然後為指標p 分配了乙個10 個位元組大小的記憶體空間,接著將這個記憶體塊的大小增加到20 個位元組。關於realloc 究竟在**分配的問題,完全由實現標準庫的程式決定。它可能在原來的地方擴充,也有可能全部另行分配(想想,如果現在要擴大儲存塊,而後面的地方已經被分配出去另有他用了,你怎麼可能在原位擴充呢?)。具體情況我們不必考慮,從抽象的層次上理解其功能就夠了。
順序表的定位操作:(巧妙的設計)
思路:要求查詢線性表中是否有與e 相同的元素,如果有則返回該元素的序號,否則返回0
1. 定位過程必須知道什麼?
答: 對哪個表進行定位,返回與哪個數相等的序列號。所以需要兩個引數
2.
怎麼進行比較控制?
答: 須對線性表中的元素都進行比較,所以應該知道線性表的長度,用乙個迴圈依次取出每個元素比較。找到回返回序號。否則返回0
int locate_list-sq (&l,e)
if (i<=l.length) then reture i
else return 0 ; }
該演算法的巧妙之處在於 巧妙的利用了++i,意思是在l 查詢不到相等的元素後跳出迴圈,i 已經先加上1 了,所以i>l.length, 返回的值是0 。
分析上程式的時間複雜度
最壞的情況下是:找到符合條件的元素在最後乙個,所以時間複雜度是o (l.length )
線性表之間的操作:
例1 :線性表la 與lb ,求a=aub;
思路:求兩線性表的並,注意集合的定義,沒有相同的元素!,乙個迴圈解決問題
void union(la,lb)
例2 :線性表la 與lb 中元素是按非遞減有序排列,求lc=laulb ;
思路:初始化乙個線性表lc ,將la 與lb 中元素比較,小的進lc 。最後再掃尾
void mergelist(la,lb,lc)
if (ai<=bi)
else
while(i<=la.length)
p=l->next ; j=1;
while ( p && j < i )
if ( !p && j > i) returnerror ;
e = p->data ;
return ok; }
單鏈表的插入操作:
思路: 在順序鍊錶中,在i 前插入乙個元素,只需要將n-i+1 個元素都向右移動一位首先將指標移動到表尾元素*(p+1)=*p . 但是鍊錶在物理上的儲存空間是不相鄰的,第i 個元素的物理位置是儲存在第i-1 個元素的指標域裡,所以,首先,我們必須找到第i-1 個元素,也就是我們需要得到第i-1 個元素的指標。
怎麼能夠得到第i-1 個元素的指標呢?
答:l 是頭指標,指向頭結點。如果我們想得到指向i-1 個元素的指標,我們應該將l 移動i - 1 次。所以應該注意,迴圈i-1 次 。
如果我們想要插入的位置不在1 <=i<=n+1 呢?
答:如果插入的位置超出表長,怎麼判斷超出了表長?如果乙個鍊錶有6 個元素,那麼從1~7 的插入位置都是合理的,如果插入的位置是7 ,那麼i-1 個元素的既6 的指標是存放在第5 個元素裡的。所以i-1 元素的指標不為空。那麼如果剛剛超出表長一位,要求插入的位置是8 ,那麼i-1 個元素即7 的指標是存放在6 裡面的,而表長是6 ,所以6 的指標為空。由此我們得出,看是否超出表長,只需要判斷i-1 個元素的指標是否為空。其次,插入位置當然不能小於1 。
下面是原始碼:
status listinsert_link (linklist l, int i , elemtype e)
if (!p && j > i-1) returnerror ;
s = (linklist) malloc (sizeof(lnode)) ;
s->next = p-.next ;
p-next = s ;
s->data = e ;
return ok ; }
PE知識複習之PE的節表
確定節表位置 dos nt頭下面就是節表.確定節表數量 節表數量在檔案頭中存放著.可以準確知道節表有多少個.節表是乙個結構體陣列.沒乙個節表表示了資料在哪,怎麼儲存.下方是節的結構體 typedef struct image section header misc dword virtualaddr...
複習鍊錶所涉及的知識點
鍊錶是一種可以動態地進行記憶體分配的結構。可以定義乙個類型別的鍊錶,也可以定義乙個結構體型別的鍊錶。知識點1 指標的意義 申請了乙個動態指標後,要不要使用語句new來為指標開闢空間取決於指標的意義 如果僅僅只是乙個位址儲存變數就不要開闢,否則當指標指向別的空間的時候會記憶體溢位 若是作為鏈節來使用則...
C 程式設計練習7 鍊錶的操作 複習
本人c語言現已全部學習完啦 本篇章節為自由發揮 我也不想,但真的有點難度 因為鍊錶的內容涉及到一點資料結構 單鏈 且下學期的課程也涉及到資料結構,所有老師並沒有太過於嚴的要求我們,安慰我們說期末考試的題也涉及的很少。可現在不會的下學期都是要還的呀。所以不能鬆懈!1,建立乙個鍊錶並輸出。我的答案如下 ...