數據結構和C語言有什麼聯繫?
本人大二學生,大一C學的一般般…
現在開設了數據結構課程,上課上的一臉懵逼。找不出有什麼聯繫…感覺上課講的都不能帶入到C程序中 感覺語法有問題,有人告訴我這是演算法語言 可是老師上課基本沒有提C 而且感覺周圍同學學起來都挺吃力的,看了網課總覺得和C之間有一道鴻溝…
C 和 C++ 是少數能準確描述內存中數據結構的語言。其他語言你定義一個數組或對象(一般只能放在 heap 上),語意倒是對的,但它往往有額外的內存開銷。C/C++ 的 array of struct 或 array of array of struct 是緊湊的(也是在內存中連續的),可以做到一個多餘的位元組都沒有。
C 和 C++ 也是少數能以不同的觀點看待(解讀)同一塊內存的語言。你定義一個 array of Point { double x, y; },必要時可以把它當成 array of double 來處理(eg. 向量化/SIMD),別的語言少有這種能力。不過 C 估計是唯一需要你手動釋放內存的語言,用別的語言學數據結構往往學不到這個技能。
沒有任何關係。數據結構是正交於語言的。任何數據結構在任何語言都能實現,因此沒必要代入一種語言。
數據結構的複雜度分析是在漸進下的,因此代入語言之後,高效實現需要考慮多得多的體系結構問題,比如緩存管理,內存讀寫機制。看題主的描述應該不是學CS的,因此了解這些是不可能的。所以題主就當這是另一門大學數學課,隨便學學,有閑情的用C實現一下,學不懂也沒什麼關係。沒有任何聯繫。
數據結構可以用C語言描述,也可以用Java描述,自然語言也可以描述。
打個比方說,要表達我愛你:
漢語:我愛你英語:I love you法語:Je t"aime無論用什麼語言,表面看上去不同,然而要表達的意思卻都是我愛你。同樣地,無論用什麼編程語言描述數據結構,形式上可能不太相同,但都是在描述同一種抽象的邏輯結構。
而常見的《數據結構(C語言版)》、《數據結構(Java語言版)》就類似於《西遊記(中文版)》、《西遊記(英文版)》。
沒有任何聯繫
數據結構是抽象數據類型和一系列演算法的具體實現,不依賴任何一種具體的語言。不過考慮到抽象數據類型的特點,其實C語言並不適合數據結構的學習——它還是更加適合使用C++或者JAVA這樣的,典型面向對象的語言來實現。國外不少高校在講數據結構的時候用的都是OOP語言——UIUC用的是C++,而UCB用的則是JAVA。
至於國內……基本上嚴蔚敏的歷史地位應該跟譚浩強是同級別的……事實上仔細觀察就能發現,基於C語言的數據結構實現,本質上其實就是「強行OOP」——只不過相當於把對象的成員強行拆分出來變成一堆亂七八糟的散亂結構體和函數而已……最後安利一發課程信息 - C++ 程序設計課程信息 - 數據結構同大二,同剛剛學數據結構C版,教材應該也是嚴XX(T大出版社的,粉紅色封面)
坐標妖都某文科211軟工
我感覺,對於數據結構,用C的typedef struct 不如用類來做……這本書有點強行上C的感覺……
一.OOP語言中函數和變數是封裝的。而諸如C語言之類的,並不是封裝的。所以基本上每個函數都需要一個ADT的引用。這是墜痛苦的。
二.C艹內存管理好一點。舉個例子,對一個ADT,就姑且叫Naive吧。
在C中,如果要構造一個Naive對象,需要一個InitNaive函數,其中還要用malloc分配內存大小,主程序結束前銷毀該對象,需要一個DestroyNaive函數,在其中還要用free之類的。在C艹中,只需要聲明一個類,叫Naive。其中Naive的構造函數就直接用Naive()或者Naive(int young,int simple)之類的。裡面寫點賦值語句就行。銷毀時用析構函數更方便了,直接用~Naive()就行了,函數體裡面直接留空,編譯器會幫你搞定。最後吐槽一下,雖然這本書沒有譚浩強那種全是i++,++i,int a,b,c; int fun()之類的,但是也有各種hin不便於正常人閱讀的xxx?xx:xx;這種語句,也有鏈表中兩個指針p,q翻來覆去的使用…要不是考試需要這本書,我估計會再換一本來看……
hin慚愧,畢竟我才剛剛學一點。雖然學校只是在第一學期開了C的課,in which教材是譚浩強的……(順便吐槽一句,感覺我校超級喜歡用T大出版社的計算機教材……搞得我看到T大和T大出版社就渾身難♂受)
C艹是上學期在豬廠雲課堂自學的,比大牛不知道低到哪裡去了……在回答中如有錯誤與不足,敬請諒解。個人覺得初學者學數據結構用C語言是最好的。Node *next多形象,其它語言再提高一層抽象,反而不利於理解內存布局。為什麼要理解內存布局?
在關鍵應用中,內存布局和性能息息相關。
數據結構,顧名思義就是結構化組織數據的方式。
大多數語言都存在的,數組,便是一種基本數據結構。
基於數組可以編寫出更多的更高級的數據結構,滿足更多的Coding需求。
字元串(String)也是一種數據結構,面向對象裡邊的類(Class)也是一種數據結構。
C、Golang裡邊的Struct很明顯是數據結構,但是函數式語言裡邊的函數也一樣是數據結構... 甚至你自己發明一個獨特的數據封裝體,也是一種「數據結構」。
所以,數據結構跟C語言或者其他語言沒有直接性的關係,並不是一個等級上的東西。數據結構是一種抽象概念,C只是可以實現這個概念的語言之一。
在某些語言例如Lua、JS裡邊,因為標準庫不提供更高級的數據結構或者語言本身沒有更高級的特性。
但是提供了靈活自由的Table以及Array等。可以實現幾乎所有的其他高級數據結構以及面向對象語言特性。常見的數據結構如下:- 數組(Array)
- 堆棧(Stack)
- 隊列(Queue)
- 鏈表(Linked List)
- 樹(Tree)
- 圖(Graph)
- 堆(Heap)
- 散列表(Hash)
最後,數據結構並不是一個死概念。不是只有上述東西才能稱為數據結構。就跟演算法類似。
當然語言上跟數據結構也是有息息相關的東西,例如 引用、指針、值級等。C語言可以讓你深刻理解什麼叫野指針,寫100行以上的函數沒提示越界我都懷疑電腦壞了...
單說這兩個概念有什麼聯繫的話,C語言(以及幾乎任何一門基於差不多的模型的語言)可以給數據結構建模;兩門課程的聯繫的話,有了C語言就可以用來實現一些數據結構,付諸實踐、學會數據結構才能寫一些複雜一點的程序。有人說不是CS專業不用學好數據結構......不說自己寫一些新的演算法,弄一些新的結構,即使是用別人寫好的庫也得了解一些常識吧?
數據結構是以離散數學為基礎的,和任何一種編程語言都沒有直接聯繫,編程語言只是能夠用來實現數據結構
關係就是數據結構可以用C語言來表示,C語言可以用來表示數據結構。其實數據結構用任何語言都可以學習的,包括JavaScript這類的腳本語言。不過感覺大學教材一般喜歡用C和C++,至於好處就是你可以學的比較徹底,在很多時候能了解到數據結構中某些設計的原因和本質,至於壞處。。。額用來表示數據結構所需要的代碼難度很低很低的,暫時說不出來有什麼壞處。
我當初和你一樣,我一開始還以為數據結構是一門語言呢,發現每門語言都有數據結構,它們表現形式又那麼不一樣。以嚴蔚敏的書為例,由於沒看前言,不知道她用的是類C語法(即偽代碼),我還以為這是C語言用來寫數據結構的特殊語法!且一開始沒有介面的概念,別人一上來就是一套規範的函數介面,新手都沒有從最基本原理建立起抽象,直接看成型的東西,只會腦袋一片空洞。
別人弄數據結構的時候又喜歡用Node來表現,看到頭都大。因為新手平時關注的都是具體實用的類型像char int之類的,如果沒數據結構思維看那些用Node表現數據結構的代碼,一看就死。
我第一次攻破數據結構,明白數據結構是什麼的契機是cs50課程的動態內存分配+我原本學java掌握的面向對象思維+博客,強擼了一個鏈表。
鏈表是最好的數據結構入門,弄明白了它就直接掌握數據結構思維,學其他數據結構就不會無從下手了。
數組(靜態)形式存儲對象(結點):
struct GirlFriend //定義一個女朋友類型
{
char *name; //女朋友名字
int age; //女朋友年齡
};
int main()
{
struct GirlFriend arr[3]; //定義一個保存女朋友的數組
struct GirlFriend g1, g2, g3; //定義3個女朋友
g1.name = "崛江由衣"; //為女朋友起名字
g1.age = 17; //女朋友年齡
g2.name = "茅野愛衣"; //為女朋友起名字
g2.age = 16; //女朋友年齡
g3.name = "伊瀨茉莉也"; //為女朋友起名字
g3.age = 15; //女朋友年齡
arr[0] = g1; //把女朋友保存到數組,需要的時候隨時拿出來
arr[1] = g2;
arr[2] = g3;
for (int i = 0; i &< 3; i++) //循環3次遍歷整個數組 { printf("女朋友的年齡是:%d ",arr[i].age); printf("女朋友的名字是:%s ",arr[i].name); } system("pause"); }
數據結構(靜態)形式存儲對象(結點):
struct GirlFriend //定義一個女朋友類型
{
char *name; //女朋友名字
int age; //女朋友年齡
struct GirlFriend *next; //不用數組保存對象就多了這個鬼東西- -!
};
int main()
{
struct GirlFriend g1, g2, g3; //定義3個女朋友
struct GirlFriend *head; //頭指針,指向數據結構的入口,相當數組首地址,用處嘛,後面就知道。
g1.name = "崛江由衣"; //為女朋友起名字
g1.age = 17; //女朋友年齡
g1.next = NULL; //初始化為NULL,方便後面的遍歷
g2.name = "茅野愛衣";
g2.age = 16;
g2.next = NULL;
g1.next = g2; //手工組織數據結構- -,靜態的數據結構真噁心。
g3.name = "伊瀨茉莉也";
g3.age = 15;
g3.next = NULL;
g2.next = g3;
//到這裡,一個簡單的靜態數據結構已經形成了,拿到g1就可以操作g1往後的所有對象
printf("女朋友的年齡:%d
", g1.age);
printf("女朋友的名字:%s
", g1.name);
printf("女朋友的年齡:%d
", g1.next-&>age);
printf("女朋友的名字:%s
", g1.next-&>name);
printf("女朋友的年齡:%d
", g1.next-&>next-&>age);
printf("女朋友的名字:%s
", g1.next-&>next-&>name);
//以上是沒有頭指針的下場
//雖說拿到g1可以訪問所有女朋友,不過不能自動遍歷也太噁心了
head = g1; //頭指針終於派上用場了
printf("
");
while (head)
{
printf("女朋友的年齡:%d
", head-&>age);
printf("女朋友的名字:%s
", head-&>name);
head = head-&>next;
}
system("pause");
}
靜態的數據結構沒什麼卵用還不如用數組,也就靜態的棧會有點用。
所以我們一般討論的都是動態數據結構,只要會申請堆(heap)內存就可以做了。#include &
#include &
#include &
#define LEN sizeof(struct student)
struct student *creat(); //函數原型,動態創建對象並自動組織成單向鏈表結構
void print(struct student *head); //函數原型,遍歷單向鏈表
struct student
{
char name[64];
struct student *next;
};
int
main(void)
{
struct student *stu;
stu = creat();
print(stu);
printf("
");
system("pause");
}
int n;
struct student*
creat() //創建學生(結點)並自動組織成單向鏈表數據結構
{
struct student *head;
struct student *p1 = NULL, *p2 = NULL;
head = NULL;
n = 0;
printf("請輸入學生名字,輸入exit退出!
");
while (1){ //循環創建結點並自動組織單向鏈表結構
p1 = (struct student *)malloc(LEN); //創建一隻學生
n++;
if (n == 1) //如果是第一次創建結點則是頭結點
{
gets(p1-&>name);
if (!strcmp(p1-&>name, "exit")){ //輸入exit則退出
free((void *)p1);
break;
}
head = p1;
p1-&>next = NULL;
printf("
成功把學生插入鏈表:%s
", p1-&>name);
p2 = p1; //由於循環,p1被覆蓋前保存到p2成為舊結點
}
else
{
gets(p1-&>name);
if (!strcmp(p1-&>name, "exit")){
free((void *)p1);
break;
}
p2-&>next = p1; //舊結點next保存新結點
p1-&>next = NULL;
printf("
成功把學生插入鏈表:%s
", p1-&>name);
p2 = p1; //由於循環,p1被覆蓋前保存到p2成為舊結點
}
}
return head; //退出後返回head以供外界遍歷
}
void
print(struct student *head){//遍歷單向鏈表
struct student *p;
printf("以下是鏈表存儲的數據:
");
p = head;
if (head)
{
do{
printf("id = %s
", p-&>name);
p = p-&>next;
} while (p);
}
}
以上這是我第一次寫的,雖然功能簡單,不過我憑它獲取了數據結構思維。
再高級一點,寫的正規一點,就是用Node(結點)了,比如你不想在學生類型上面嵌套一些無關的屬性,就可以:
struct Student
{
char name[64];
int age;
};
struct Node
{
struct Student *key;
struct Node *next;
}
int
List_Insert(struct Node *head, struct Student *fuck)
{
if (head == NULL || fuck == NULL)
{
return -1;
}
struct Node *node = Init_Node();
node-&>key = fuck;
while (head-&>next)
{
head = head-&>next;
}
head-&>next = node;
return 0;
}
一個完整的數據結構函數有書上那麼多吧,數據結構比較好玩的是你不實現所有功能也run的起來,所以為了快點看到效果,一般首先實現插入和遍歷函數。
沒半毛錢關係
不厚道的猜一下,你們教材是嚴蔚敏?趕緊換一本正常的書看
前面答的都很好了。當年我們講數據結構的時候,用的是c語言。我不喜歡c,問老師能不能用c++,老師比較開明同意了。從此之後的作業到考試,我用的都是c++,沒有任何問題。你要是喜歡Java也可以用,但是我覺得棧結構,用c語言能夠直接管理內存,對之後的學習會有比較大的幫助
骨頭和肉的關係。相互依存,數據結構靠代碼來表達。java,c,都沒區別。就像你是肥肉,瘦肉,五花肉一樣,都是長在骨頭上的
因為本來就沒有關係。
數據結構所考慮的主要問題是,數據在計算機中,以怎麼樣的抽象組織形式存在,以方便我們寫可讀、高效的代碼。這個形式,並不依賴於具體的語言。======================================================
數據結構的正確學習姿勢是,理解並運用。
運用,就是用任何編程語言,把你學到的數據結構表達出來。C語言當然是一個經典的語言了。
但是前提是理解。如果不理解的話,你就搞不清楚,你這個東西要怎麼寫,寫出來更是無從談起。比如最簡單的,單鏈表:struct Node{
int data;
Node* next;
};
struct Node* head;
其實畫出來很簡單:
( -&> 表示指向)
頭指針-&>節點1-&>節點2-&> ... -&>節點N-&> NULL
每個節點要有用,就有數據域。
要表示指向,我們自然而然地去使用指針。它們打個包,放在一個struct里,就是一個Node(節點)了。
==================================
我個人觀點:數據結構不是讀文字、聽講解的課。數據結構是一門,畫圖畫出來,理解清楚,然後用你學會的任何一門編程語言實現出來的課。大二計算機課程基本上不是自學搞定的么..最關鍵還是要自己去折騰呀...c / cpp 他們有一些缺陷(大家都知道Linus的吐槽) 但是是一門很好的用來學習數據結構的語言 也是一門很有用的語言 多對著reference看看 細節的話去看看primer plus之類的外國書 然後就去碼代碼吧。。。我校老師不講什麼語法 也不用什麼書 直接丟一些讓人生無可戀的作業以及動不動弄一些contest(在hackerrank上) 大家各憑本事吧...當然作弊被發現會很慘很慘很慘
數據結構是一種基於離散數學組織和存儲數據的方式。類似一個模型。 c語言等其他語言是需要藉助數據結構這個模型,進一步實現演算法。
數據結構講的是數據與數據之間的邏輯結構以及物理結構,一種邏輯結構(人們想像的數據與數據的關係)可以對應多種物理結構(即在計算機上內存上具體的存放方式),然後在這個模型下有一系列的操作。叫做數據結構。所以在設計程序的時候,首先要決定自己的數據結構是什麼樣子的,比如說用線性表好還是鏈表好,或者用樹?只是決定了數據的存放方式。然後在這種數據結構下設計一個演算法。就可以實現相對應的功能。所以說程序=數據結構+演算法。演算法,題主應該知道了,演算法不依託任何語言來實現,所以演算法可以用c語言表示。往往用你最熟悉的東西來表示陌生的東西比較合適,所以說C語言和數據結構沒有太多關係,只是一種表述形式。
C語言類似於語法規範,數據結構是把一組相關的數據包裝起來,這樣結構更清晰使用起來更方便
推薦閱讀:
※為什麼C語言沒有String類型?
※要開發一個jvm需要哪些知識?
※學習C++,關於小項目練手的問題總是感覺不知道從哪入手?
※有哪些go或c++框架可以完整模擬瀏覽器訪問網頁所涉及的全部元素?
※現代編譯器是如何實現自定義函數在main()函數之後實現的呢?