單鏈表和順序儲存結構的區別:
1.單鏈表不像順序儲存結構這麼集中,它可以很散,是一種動態結構;
2.對每個鍊錶來說,它所占用空間的大小和位置是不需要預先分配劃定的,可以根據系統的情況和實際的需求即時生成。
所建立單鏈表
的過程就是乙個動態生成鍊錶的過程。即從「空表」的初始化狀態起,依次建立各元素結點,並逐個插入鍊錶。
單鏈表整表建立的演算法思路:
1.宣告乙個結點p和計數器變數i;
2.初始化一空鍊錶l;
3.讓l的頭結點的指標指向null,即建立乙個帶頭結點的單鏈表;
4.迴圈:
& 生成一新結點賦值給p;
& 隨機生成一數字賦值給p的資料域p->data;
& 將p插入到頭結點與前一新結點之間;
實現單鏈表整表建立**演算法如下:
/*隨機產生n個元素的值,建立帶表頭結點的單鏈線性表l(頭插法)*/
void createlisthead (linklist *l, int n )
}
這段演算法**裡,我們其實用的是插隊的辦法,就是始終讓新結點在第一的位置。我們可以把這種演算法簡稱為頭插法。如圖:
可事實上,我們還是可以不這樣幹,為什麼不把新結點都放最後呢?這才是排隊的正常思維,所謂先來後到。
我們把每次新結點都插在終端結點的後面,這種演算法稱之為尾插法。
實現尾插法**演算法如下:
/*隨機產生n個元素的值,建立帶表頭結點的單鏈線性表l(尾插法)*/
void createlisttail (linklist *l, int n )
r->next = null; /*表示當前鍊錶結束*/
}
注意l與r的關係,l是指整個單鏈表,而r是指向尾結點的變數,r會隨著迴圈的不斷變化結點,而l則是隨著迴圈增長為乙個多結點的鍊錶。
這裡需要解析一下,r->next=p 是將剛才的表尾端結點r的指標指向新結點p; (難點:) r =p就不是很好理解了,是什麼意思?看圖:
它的意思是,就是本來r是在ai-1元素的結點,可現在它已經不是最後的結點了。(其實r就是乙個尾節點的標誌,當r沒有在尾時,必須把它移到尾)
迴圈結束,那麼應該讓這個鍊錶指標域置空,因此有了「r->next=null」以便以後遍歷時可以確認其尾部。
個人思考附加:
附加一:
頭插法和尾插法的區別:
頭插法:頭指標裝null,每次從後面新增元素,null尾都要往後挪乙個地方;
尾插法:頭指標沒有裝null,每次從後面新增元素,新增完後,再在尾指標裝null;
附加二:
srand函式是隨機數發生器的初始化函式。
原型:void srand(unsigned seed);
用法:它需要提供乙個種子,這個種子會對應乙個隨機數,如果使用相同的種子後面的rand()函式會出現一樣的隨機數。如: srand(1); 直接使用1來初始化種子。不過為了防止隨機數每次重複常常使用系統時間來初始化,即使用 time函式來獲得系統時間,它的返回值為從 00:00:00 gmt, january 1, 1970 到現在所持續的秒數,然後將time_t型資料轉化為(unsigned)型再傳給srand函式,即: srand((unsigned) time(&t)); 還有乙個經常用法,不需要定義time_t型t變數,即: srand((unsigned) time(null)); 直接傳入乙個空指標,因為你的程式中往往並不需要經過引數獲得的t資料。
函式一:int rand(void);
從srand (seed)中指定的seed開始,返回乙個[seed, rand_max(0x7fff))間的隨機整數。
函式二:void srand(unsigned seed);
引數seed是rand()的種子,用來初始化rand()的起始值。
可以認為rand()在每次被呼叫的時候,它會檢視:
1) 如果使用者在此之前呼叫過srand(seed),給seed指定了乙個值,那麼它會自動呼叫
srand(seed)一次來初始化它的起始值。
2) 如果使用者在此之前沒有呼叫過srand(seed),它會自動呼叫srand(1)一次。
根據上面的第一點我們可以得出:
1) 如果希望rand()在每次程式執行時產生的值都不一樣,必須給srand(seed)中的seed乙個變值,這個變值必須在每次程式執行時都不一樣(比如到目前為止流逝的時間)。
2) 否則,如果給seed指定的是乙個定值,那麼每次程式執行時rand()產生的值都會一樣,雖然這個值會是[seed, rand_max(0x7fff))之間的乙個隨機取得的值。
3) 如果在呼叫rand()之前沒有呼叫過srand(seed),效果將和呼叫了srand(1)再呼叫rand()一樣(1也是乙個定值)。
rand () %100 即隨機生成100以內的數;
當我們不打算使用這個單鏈表時,我們需要把它銷毀,其實也就是在記憶體中將它釋放掉,以便留出空間給其他程式設計師或軟體使用。
單鏈表的整表刪除的演算法思路如下:
1.宣告一結點p和q;
2.將第乙個結點賦值給p;
3.迴圈:
& 將下一結點賦值給q;
& 釋放p;
& 將q賦值給p;
實現單鏈表的整表刪除**演算法如下:
/*初始化條件:順序線性表l已存在,操作結果:將l重置為空表*/
status clearlist (linklist *l)
(*l)->next =null; /*頭結點指標域為空*/
return ok;
}
這段**裡,常見的錯誤就是由同學會覺得q變數沒有存在的必要。在迴圈體內直接寫free(p);p=p->next ;即可,可這樣帶來什麼問題?
要知道p是乙個結點,它除了有資料域,還有指標域。你在做free(p)時,其實時在對它整體結點進行刪除和記憶體釋放工作。
怎麼說呢?你看懂《大話資料結構》--學習筆記9 ***重點***
尾插法中的那句:「r=p」 了嗎?如果看懂了 ,這個也應該沒問題的。因為他們類似的,都起到乙個指標傳遞的作用。
《大話資料結構》 學習筆記1
第一章 資料結構緒論 經典 if you give someone a program you will frustrate them for a day if you teach tem how to program,you will frustrate them for a lifetim.如果...
《大話資料結構》 學習筆記2
第二章 演算法 2.2 資料結構 與 演算法的關係 簡單的說 資料結構 與 演算法 的關係 即 梁山伯 與 祝英台 的關係 把其中一方隔離出來唱獨角戲.沒意義!2.3 兩種演算法的比較 現寫乙個求1 2 3 100結果的程式,你應該怎麼寫呢?大多數人馬上寫出下面的c語言 int i,sum 0,n ...
《大話資料結構》 學習筆記5
線性表的順序儲存結構,指的是用一段位址連續的儲存單元依次儲存線性表的資料元素。線性表 a1,a2,a3,an 的順序儲存示意圖如下 a1a2 ai 1 ai.an 線性表的順序儲存結構,說白了,就是 在記憶體中找了塊地兒,通過佔位的形式,把一定的記憶體空間給佔了,然後把相同資料型別的資料元素一次存放...