之前跟著朱老師寫的乙個帶頭結點的:
建立鍊錶時有兩種方法,
一種是先初始化(建立乙個空鍊錶),然後對這個空鍊錶進行結點輸入,建立鍊錶;這個時候,由於已經有了頭結點,將其傳入,直接在頭結點的後面進行操作;
另外一種是將初始化和建立鍊錶放到乙個函式裡,這時候傳入的鍊錶就什麼都沒有,連頭結點也沒有;先建立頭結點,讓傳入的指標指向頭結點,接著繼續輸入資料; 也有的書上是什麼都不傳入,最後生成乙個鍊錶後傳出這個鍊錶。
插入找前驅(第k個位置的前驅)
刪除找前驅
//這個要從頭結點開始
//如果在第1個位置插入,前驅就是頭結點
for(pre = (*l); pre && i < k-1; i++)
if(!pre)
//這個要從頭結點開始
//如果要刪除第1個位置的結點,前驅就是頭結點
for(pre = (*l); pre->next && i < k-1; i++)
if(pre->next == 0)
這幾天寫的這些個程式還有乙個小缺陷,就是那個要修改鍊錶資料的形參中,並不需要使用**l,用*l就可以;因為即使這個是傳值,但是傳的是指標的值,指標指向的內容是不變的。
#include#includetypedef unsigned char boolean;
#define true 1
#define false 0
typedef int elemtype;
typedef struct lnodelnode;
/*//有些書上描述鍊錶這樣子描述,就是多定義了乙個指向結點的指標而已
typedef struct lnodelnode, *linklist;
*/void initlinklist(lnode **l); //初始化的意思是構造乙個空鍊錶
void createlinklist(lnode **l); //尾插法 由於之前已經初始化建立了空鍊錶,所以這個函式傳入的鍊錶就直接加有效資料結點就可以了
void createlinklist2(lnode **l); //頭插法 尾插法需要乙個指標,始終指向末結點 頭插法則不用
//輸出鍊錶
void printlinklistdata(lnode *l);
//查詢
elemtype getelem(lnode *l, int k); //找出帶頭結點單鏈表中第i個位置的結點的資料
lnode *getelem2(lnode *l, int k); //找出帶頭結點單鏈表中第i個位置的結點的指標
lnode *locateelem(lnode *l, elemtype x); //找到帶頭結點單鏈表中值為x結點的指標
//插入
void insertelem(lnode **l, int k, elemtype x); 在帶頭結點單鏈表中第i個位置上插入新結點
//這就意味著是前插,但是所有的前插都是找到該結點的前驅結點,然後再進行後插
//刪除
void deleteelem(lnode **l, int k);
boolean isempty(lnode *l);
int lengthoflinklist(lnode *l); //鍊錶長度
int lengthoflinklist(lnode *l)
return i;
} boolean isempty(lnode *l)
void deleteelem(lnode **l, int k)
for(pre = (*l); pre && i < k-1; i++)
if(!pre)
p = pre->next; //p指向要刪除的結點
pre->next = p->next;
free(p);
printf("刪除完畢!\n");
*/ //找前驅結點
if(k < 1)
for(pre = (*l); pre->next && i < k-1; i++)
if(pre->next == 0)
p = pre->next; //p指向要刪除的結點
pre->next = p->next;
free(p);
printf("刪除完畢!\n");
} //這就意味著是前插,但是所有的前插都是找到該結點的前驅結點,然後再進行後插
void insertelem(lnode **l, int k, elemtype x)else if(k == 1)else if(k = 1)else
//printf("pre->data=%d\n", pre->data);
*/ //找前驅結點
if(k < 1)
for(pre = (*l); pre && i < k-1; i++)
if(!pre)
//為新結點開闢空間
p = (lnode *)malloc(sizeof(lnode));
p->data = x;
p->next = pre->next;
pre->next = p;
printf("插入完畢!\n");
} //從單鏈表第乙個結點開始,由前往後依次比較表中各結點資料域的值,若某結點資料域的值等於x,則返回該結點的指標;
//若整個單鏈表中沒有這樣的結點,則返回null
lnode *locateelem(lnode *l, elemtype x)
return p; //返回值為x的結點的指標,如果沒有這樣的值,p=null,直接返回p即可
} //在單鏈表中從第乙個結點出發,順指標next域逐個往下搜尋,直到找到第k個結點為止,否則返回最後乙個結點指標域null
lnode *getelem2(lnode *l, int k)
while(p && i < k)
return p; //返回第k個結點的指標,如果k大於表長,p=null,直接返回p即可 }
elemtype getelem(lnode *l, int k)
while(p && i < k)
if(!p)
return p->data; }
void printlinklistdata(lnode *l)
printf("\n");
} void createlinklist2(lnode **l) }
//下面的這個建立鍊錶的方法,是把初始化和建立鍊錶放到了一起,即傳入的鍊錶什麼都沒有,連頭指標都沒有
void createlinklist(lnode **l) }
/*void createlinklist(lnode **l)
}void initlinklist(lnode **l)else}*/
void main(void); //這樣子的話,直接定義了乙個結點,並且賦初值為0,就相當於定於了乙個空鍊錶
lnode *list = null; //這樣子的話,只是定義了乙個指標,並沒有具體的開闢結點空間,所以需要初始化,構造乙個空鍊錶
createlinklist(&list);
printlinklistdata(list);
//printf("第%d個地方的值為:%d\n", 2, getelem(list, 2));
//printf("第%d個地方的值為:%d\n", 2, (getelem2(list, 2))->data);
//printf("值為%d的結點的指標所指向的值為:%d\n", getelem(list, 2), (locateelem(list, getelem(list, 2)))->data);
//insertelem(&list, 6, 6);
//printlinklistdata(list);
deleteelem(&list, 5);
printlinklistdata(list);
printf("鍊錶是否為空:%d\n", isempty(list));
printf("鍊錶長度為:%d\n", lengthoflinklist(list));
}
c資料結構線性表之單鏈表 帶頭結點 基本操作
include include define maxsize 10 define elemtype char define ok 1 define error 0 typedef struct node 結點型別定義 node,linklist linklist為結構體指標型別 換行函式 void ...
資料結構 線性表之單鏈表
線性表 亦作順序表 是最基本 最簡單 也是最常用的一種資料結構。線性表中資料元素之間的關係是一對一的關係,即除了第乙個和最後乙個資料元素之外,其它資料元素都是首尾相接的。線性表有兩種儲存結構 順序儲存結構,即儲存單元在一段連續的位址上儲存,常見的陣列就是順序儲存結構的線性表 鏈式儲存結構,即儲存單元...
資料結構 帶頭結點的單鏈表
比較坑爹的基礎啊,大把時間浪費在建構函式上,建構函式 出生決定命運!自己解決的bug,感覺還不錯。其實程式的核心是演算法,演算法建立在資料結構的基礎之上。大部分的程式設計師現在學的基本都是規則,而不是創造。但掌握了規則,也能創造很多財富。重新鞏固我弱爆了的資料結構,沒敲完資料結構的程式設計師不是好領...