李向華, 王震, 高超
1.西北工業大學 光電與智能研究院,西安 710000;2.西北工業大學 網絡空間安全學院,西安 710000
瑞士計算機科學家尼古拉斯.沃斯(Niklaus Wirth)提出的影響深遠的“算法+數據結構=程序”(Algorithm+Data=Programs)[1]公式,成為計算機科學特別是軟件科學的指導思想,同時這個公式也說明了程序設計語言和數據結構這兩門課程之間的關系[2].
C程序設計和數據結構是計算機相關專業兩門非常重要的基礎必修課.利用C語言實現的數據結構必然以C程序設計為先導課程,利用C語言具體表達數據在計算機中的存儲和算法實現.學生對數據結構相關知識的學習,不僅理解了數據結構、算法和程序之間的關系,也是對C語言知識的鞏固和深化,使學生具有解決實際問題的能力.所以,C程序設計和數據結構關系緊密,在一定程度上影響學生對計算機學科的學習興趣.然而,筆者在翻閱大量的C程序設計相關教材時發現,C語言課程過多注重其語法體系,授課教師也基本按照教材的流程進行講解,因此,很多學生學習過C語言后,不了解其實際應用效果,也不能順暢地編寫程序.在學習數據結構課程過程中,無論算法設計還是程序書寫上,尤其涉及到指針部分,學生都覺得晦澀難懂,不會靈活應用,上機實踐時更是無從下手.這些現象說明教師在講授C語言和學生在學習C語言的過程中沒能結合適應數據結構的方法.
基于此,有必要在C語言的教學中,為數據結構課程的開展做些鋪墊,讓學生在一種輕松、有興趣的氛圍中學習,讓數據結構變成相對容易學習的學科.同時,通過C語言的學習,培養學生的邏輯思維能力、算法設計能力和創新能力[3-5].
C語言課程的內容主要圍繞結構化程序設計展開,即順序、選擇、循環三個基本結構[6-7],為了能實現這三種結構,前期要學習數據類型、輸入輸出語句等,為了處理稍復雜的問題,后期在三種結構的基礎上學習函數、數組、指針、結構體、文件等.C語言課程的主要內容如圖1所示,其中箭頭表示授課的先后順序.它與數據結構的關系如圖2所示.
根據圖2可以看出,數據結構課程主要講授兩大類數據在計算機中的存儲和實現,即線性數據(線性表、棧、隊列、串等)和非線性數據(樹、圖等)[8-9],主要操作是數據的增、刪、改、查.其中線性存儲結構是非線性結構的基礎,而線性結構的基礎又是C語言中的數組、指針、函數和結構體,故而應在學習C語言的過程中把這幾部分知識重點講解,讓學生多加練習,學精學透.如此,學生們在進行數據結構的學習后,會順利過度,無縫銜接,也會進一步提升學生們的學習興趣和解決實際問題的能力.因此,教師在講授C語言的過程中,必須有所側重、有的放矢,為學習數據結構做好準備.

圖1 C程序設計主要內容

圖2 C語言相關內容與數據結構之間的關系
從如何學好數據結構這門課程來看,目前的C語言教學過程中存在如下主要問題:
(1) 總體來看,過于注重語法體系,實驗課內容淺顯.C語言是學生接觸到的第一門程序設計語言,而學生的學習精力大多用在簡單程序的編寫上.教學過程中發現,在循環結構學習之前,絕大部分同學都能跟上節奏,然而當循環、函數、數組、指針、結構體等內容展開后,開始陸續有學生掉隊.這說明我們在平時的授課和實驗過程中,對相對難點投入的時間和深度不夠,使得學生在處理復雜問題時缺乏經驗和能力.而數據結構的學習又恰恰以數組、函數、指針和結構體為基礎,這個環節的薄弱導致了學習數據結構不能得心應手.
(2) 從具體內容來看,存在如下問題:
①從C語言到數據結構命名形式的跳變.在C語言的教學過程,雖然講授了變量、函數名等的命名規則,如做到見名知意、駝峰命名法等,但因為教材中的例題簡單,采用的命名法也相對簡易,如變量名和數組名用a、b、c等,函數名使用f1、f2等.雖然對初學者來說,這樣的命名簡單、易寫,但是過渡到數據結構中,卻非常不適應,仿佛學的是兩種語言.如數據結構中初始化線性表的函數名InitList_Sq,建立鏈表的函數名為CreateList_L,圖的頂點數目常量MAX_VERTEX_NUM等.在數據結構中的變量和函數名雖然稍顯復雜,但真正做到了見名知意,增加了程序的可讀性.
②指針內容講授過于泛化.眾所周知,指針是C語言的核心和精華,指針的使用除了可以使程序簡潔、緊湊和高效外,有些情況非用指針不可,比如數據結構中鏈表、樹、圖的構建.在有些無法用值傳遞完成的問題中,可以用指針來完成,如在子函數中完成兩個數的交換.然而,在C語言的教學中,根據教材內容講授往往淺顯且寬泛,并無針對性地重點講指針的具體應用,給學生的感受是指針可用可不用,指針麻煩難懂,可被替代,完全沒有體會出其精髓所在,過度到數據結構時,老師又花費大量時間幫助學生理解指針的用法和妙處,增加了數據結構學習的難度.
③結構體部分的講解過于簡略.在C語言的學習過程中,由于課本例題、習題以及實驗內容偏簡單,似乎不用太多結構體的知識,加之課時有限,很多老師就把該部分作為略講和選講的內容,以至給學生帶來結構體不重要的錯覺.然而結構體在數據結構的學習過程中,貫穿始終,有時候還層層嵌套,比如圖的鄰接表的存儲表示[9],如圖3所示.
圖的實現屬于數據結構中偏后部分的知識,但仍有部分同學不能很好地理解這種嵌套的結構體,都是源于C語言基礎薄弱.

圖3 結構體在數據結構中重要性示例
④算法設計思想薄弱.在C語言的學習過程中,由于內容比較淺顯,例題、練習題和實驗內容都比較簡單,所以同學們算法設計思想淡薄.雖然學習了流程圖,但幾乎在整個C語言的學習過程中沒有用到,致使學生們養成了遇到問題沒有過多的思考和設計就直接編碼的習慣,結果形成了編了刪、刪了再編的低效率學習,也使得同學們在學習數據結構的過程中,由于問題的復雜,而變得束手無策,算法設計不成體系.
為了解決上述在C語言教學中存在的問題,現提出以下對應整改措施.
(1) 總體上側重實際應用.由于以往C語言的教學過程中,程序相對簡單,所以學生在編寫過程中會存在這樣的困惑,編寫這樣的程序有什么用?有些老師還會花費大量時間去講解在實際應用中使用率不高的語法點,導致學生的學習熱情不高.所以,我們應該以解決實際問題為出發點,以問題為導向開展C語言的教學.比如講解變量的數據類型時,不用面面俱到,只講最常用和實用的int、float、double、char的基礎知識;講解自增、自減運算符時,只介紹i++(i--)和++i(--i)的區別即可,其余知識請學生自學;在講解輸入輸出語句時,也只講解最為常用的幾對輸入輸出語句即可,如printf和scanf、putchar和getchar、puts和gets等,在實際應用中再次強化.這樣,我們利用較少的時間學習最實用的這部分基礎知識,結余出更多時間去學習后面的循環、數組、函數和指針等難點部分,為數據結構的學習打好基礎.
(2) 具體內容來看,措施如下:
①養成良好的編程風格.既然C語言是學生接觸到的第一門編程語言,那它也擔負著學生習慣養成的重大使命.這個習慣主要是指算法設計和編寫可讀性強的程序.面對復雜問題時,我們要培養學生化繁為簡、有步驟各個擊破的思想,即利用函數解決一個個小問題,每個函數只實現一個子功能.由于函數的高內聚性,設計它就變得容易了.
編寫可讀性強的程序則要求學生們做到以下幾點[10]: a. 注意程序的視覺組織,采用階梯縮進形式使程序結構清晰明顯;b. 變量、函數的命名做到見名知意;c. 給每個函數加序言性注釋,重要的變量、語句等加解釋性注釋.
例如圖4所示的代碼[11],雖然功能簡單,但可讀性強.這樣的編程風格,更加有利于學生們過渡到數據結構的學習中.

圖4 程序可讀性舉例
②指針部分重點講解與數據結構結合強的知識點.指針是C語言中的重點和難點,然而在C語言的教學過程中,過多地注重了指針的語法,而非應用.在C語言的大部分教材中,有一節詳細地講述了一維數組、二維數組與指針的關系,以及指針數組和數組指針,給學生的體會是指針并無太大用處,是否使用指針都可以實現數組的操作.為避免學生們對指針認知上的偏差,除了指針的基礎知識外,我們應該花大量篇幅去學習必須使用指針的情況、指針與函數的關系、動態內存分配中涉及到的指針知識以及結構體與指針.站在利用數據結構解決實際問題的角度,指針貫穿始終,從順序結構的鏈表到層次結構的樹和網狀結構的圖,沒有指針難以實現.以鏈表為例,鏈表節點的定義包括了指針與結構體的關系;鏈表的創建除了指針與結構體的關系,還包括了指針與動態分配內存的關系;鏈表的刪除包括了指針與函數的關系等.總之,指針的重要作用無可取代,所以我們應該重點講授與數據結構存儲相關的指針知識點,可適當滲透數據結構相關知識,引起學生興趣與重視.
③結合數據結構的順序表學習數組和結構體.數據結構中的順序表本質結構是一維數組,但通過動態申請獲得空間,利用結構體整合數組,同學們會覺得晦澀難懂,這都源于C語言學習過程中老師未曾從數據結構角度進行講解.所以,當學生們學完基本的數組基礎知識后,可以適當擴充,數組不僅可以靜態產生,也可以動態申請,而且動態申請的空間彌補了靜態不能動態增長的弊端.數組的學習也可以引出結構體相關知識,例如有些實際問題不能預估具體數據量,故會定義較大數組存儲少于數組長度的數據,使得數組中實際數據個數與該數組息息相關,這樣我們就可以把數組和它的實際長度封裝在一起,利用結構體實現.通常情況下,在C語言的教材中,動態申請空間的兩個函數malloc和remalloc以及結構體都是放在最后面學的,講解也比較粗略,學生們也沒有應用場景,自然體會不到它們的真正作用.
經過把順序表和數組學習的結合,讓同學們深切感受到了結構體和動態申請空間函數的實際應用,做到了有的放矢,能夠學以致用,更能提高學習興趣.同時,也可以把書上的例題和習題按動態申請數組空間和利用結構體封裝的思想再練習一遍.這樣,學生們學習數據結構時候就會銜接順利,再學習棧、隊列的時候也更得心應手.
④強化算法設計思想.如果我們在學習和講授C語言的過程中,注重實際應用且執行上述措施,學生潛移默化中就有了算法設計的思想.在講解具體題目時,除了自然語言描述算法思想外,教師再配以流程圖、偽碼等描述算法的工具,學生慢慢就會養成先思考、再編程的習慣.
鑒于學生們對學習數據結構的迷茫和畏難心里,我們需要從根本上解決問題,即把其基礎——C語言程序設計學透、學牢.故本文針對C語言教學中存在的主要問題加以分析并給出了相應的解決措施.此外,本人通過走訪、調研學生心聲發現,絕大多數學生希望這兩門課程由一名教師授課,形成兩學期課程的連續性.
本文所闡述的內容不是在C程序設計過程中簡單地添加數據結構知識,而是以數據結構為導向的深入學習C語言知識,并滲透數據結構算法的思想,同時培養學生的邏輯思維能力和創新能力.故對學生的考核應以實際動手能力為主,合理選用教材.本人下一步的主要工作就是重新編寫融入數據結構思想的C程序設計教材.