c語言鏈表庫
⑴ 關於c語言鏈表
因為你只創建了一個啊,你的本意是用create函數執行創建鏈表的工作,不管多少個都是由它完成的,但是你的create函數明明沒有while循環或者dowhile循環啊,只做了一遍啊,第一遍的if做完了,第一個鏈表完成了,再次scanf了之後,就退出來了啊,在你創建了一個鏈表之後,就在那個鏈表的尾部寫入NULL了,程序就結束了啊,又沒一直做scanf,和創建鏈表的工作。create沒循環啊,列印鏈表是沒錯啊,輸出了第一個啊,你自己創建的第一個叫head,只有後面的鏈接,自己本身沒有存放任何數,只輸出了第二個鏈表,第二鏈表的next就是NULL了,輸出當然就停止了啊。
怕我沒說清楚,或者把你繞暈了,所以我截個圖給你看。
你這個if只做了一遍啊,沒有循環啊,然後就再次用scanf了,然後呢?然後就退出if了吧,然後就執行了r->next=NULL;對吧,r不就是你創建的第一個有數據的鏈表嗎?然後就return h了,那麼只有一個啊,有循環嗎?scanf了之後,也沒判斷數值啊,不是-1,應該繼續做啊。
解決方案:在這個if的外面,加一個do while的循環,然後判斷scanf讀入的n的值,應該就可以了。
⑵ C語言如何創建單鏈表
C語言創建單鏈表如下:
#include"stdio.h"
#include"stdlib.h"
#include"malloc.h"
#include "iostream.h"
typedef struct node
{
intdata;
node * next;
}node , * List;
void create(int n)
{
int c;
List s,L;
L=(List)malloc(sizeof(node));
L->next=NULL;
printf("請輸入第1個數據:");
scanf("%d",&c);
L->data=c;
for(int i=2;i<=n;i++)
{
s=(List)malloc(sizeof(node));
printf("請輸入第%d個數據:",i);
scanf("%d",&c);
s->data=c;
s->next=L;
L->next =s;
}
printf("鏈表創建成功!");
}
void main()
{
int n;
printf("請你輸入鏈表的個數:");
scanf("%d",&n);
create(n);
}
⑶ C語言裡面的鏈表是什麼
C語言裡面的鏈表是一種數據結構
是一種線形的存儲結構
鏈表和數組一樣,也是將一組同類型的數據組織在一起的一種數據結構
不同的是
數組採用的是順序存儲,依靠數組的首地址和元素的相對地址(下標)來實現訪問。
優點是訪問方便快捷,而缺點是數組是靜態的,不利於實現元素的動態增減。
而鏈表採用的是離散存儲,依靠節點間的指向下一個節點的指針來實現訪問。
其優缺點和數組相反
⑷ c語言怎麼把鏈表數據寫進mysql
方法如下:
1.頭文件:
#include
#include
#include//這個是必需要包含的,下面對mysql的所有操作函數,都出自這里
2.定義一個MYSQL變數:
MYSQLmysql;
這里MYSQL是一個用於連接MySql資料庫的變數。
在後面對mysql資料庫的操作中,我們就用這個MYSQL變數作為句柄的。
3.定義資料庫參數:
charhost[32]=」localhost」;
charuser[32]=」username」;
charpasswd[32]=」pwd」;
chardbname[32]=」testdb」;
4.資料庫操作
1).初始化資料庫:
mysql_init(&mysql);
2).連接資料庫:
mysql_real_connect(&mysql,host,user,passwd,dbname,0,NULL,0);
我們在操作時,可以對以上的函數進行if測試,如果初始化或者連接出錯,作出相應提示,以便調試。
5.對資料庫的操作:
Mysql_query(&mysql,「select*fromtestdbwherecondition」);
我們在實際操作中,為了更方便的使用程序中的某些變數,我們將會用到一個函數:
intsprintf(char*str,constchar*format,?);
這個函數用來格式化我們的字元串,然後將變數按照給你的格式,賦給第一個參數。
我們使用這個方法方法可以很方便的使用我們的變數來對資料庫進行操作。例如我們將要進行資料庫的查詢操作,我們就可以這樣使用:
sprintf(sql,」select*fromtestdbwhereusername=『%s』」,u_name);
然後使用mysql_query(&mysql,sql)進行查詢。
MySQL是一個關系型資料庫管理系統,由瑞典MySQLAB公司開發,屬於Oracle旗下產品。MySQL是最流行的關系型資料庫管理系統之一,在WEB應用方面,MySQL是最好的RDBMS(,關系資料庫管理系統)應用軟體之一。
鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。相比於線性表順序結構,操作復雜。由於不必須按順序存儲,鏈表在插入的時候可以達到O(1)的復雜度,比另一種線性表順序錶快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而線性表和順序表相應的時間復雜度分別是O(logn)和O(1)。
⑸ 如何用C語言編寫一個鏈表
#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"
struct Node
{
int data;//數據域
struct Node * next;//指針域
};
/*************************************************************************************
*函數名稱:Create
*函數功能:創建鏈表.
*輸入:各節點的data
*返回值:指針head
*************************************************************************************/
struct Node * Create()
{
struct Node *head,*p1,*p2;
head = NULL;
p1 = p2 = (struct Node *)malloc(sizeof(struct Node));
printf("Input the linklist (Input 0 to stop):\n");
scanf("%d",&p1->data);
while(p1->data!=0)
{
if(head == NULL){
head = p1;
}else{
p2->next = p1;
p2 =p1;
}
p1 = (struct Node *)malloc(sizeof(struct Node));
scanf("%d",&p1->data);
}
p2->next = NULL;
return head;
}
/*************************************************************************************
*函數名稱:insert
*函數功能:在鏈表中插入元素.
*輸入:head 鏈表頭指針,p新元素插入位置,x 新元素中的數據域內容
*返回值:無
*************************************************************************************/
void insert(struct Node * head,int p,int x)
{
struct Node * tmp = head;
struct Node * tmp2 ;
int i ;
for(i = 0;i<p;i++)
{
if(tmp == NULL)
return ;
if(i<p-1)
tmp = tmp->next;
}
tmp2 = (struct Node *)malloc(sizeof(struct Node));
tmp2->data = x;
tmp2->next = tmp->next;
tmp->next = tmp2;
}
/**************************************************************************************
*函數名稱:del
*函數功能:刪除鏈表中的元素
*輸入:head 鏈表頭指針,p 被刪除元素位置
*返回值:被刪除元素中的數據域.如果刪除失敗返回-1
**************************************************************************************/
int del(struct Node * head,int p)
{
struct Node * tmp = head;
int ret , i;
for(i = 0;i<p;i++)
{
if(tmp == NULL)
return -1;
if(i<p-1)
tmp = tmp->next;
}
ret = tmp->next->data;
tmp->next = tmp->next->next;
return ret;
}
/**************************************************************************************
*函數名稱:print
*函數功能:列印鏈表中的元素
*輸入:head 鏈表頭指針
*返回值:無
**************************************************************************************/
void print(struct Node *head)
{
struct Node *tmp;
for(tmp = head; tmp!=NULL; tmp = tmp->next)
printf("%d ",tmp->data);
printf("\n");
}
/**************************************************************************************
*函數名稱:main
*函數功能:主函數創建鏈表並列印鏈表。
**************************************************************************************/
int main(){
struct Node * head = Create();
print(head);
return 0;
}
⑹ 請問c語言怎麼把寫進資料庫中的鏈表再次讀入新的鏈表中
首先,讀資料庫數據,把各個欄位的信息保存在相應類型的變數中
其次,malloc一個鏈表節點,將第一步中讀取的數據賦值給該鏈表節點
最後,將該節點插入鏈表中
⑺ c語言中創建動態鏈表
給你些資料吧~仔細看,看完就明白鏈表了
10.7 用指針處理鏈表
10.7.1鏈標概述
鏈表是一種常見的重要的數據結構.它是動態地進行存儲分配的一種結構.我們知道,用數組存放數據時,
必須事先定義固定的長度(即元素個數).比如,有的班級有100人,而有的班只有30人,如果要用同一個數組先後存放不同班級的學生數據,則必須定義長度為100的數組.如果事先難以確定一個班的最多人數,則必須把數組定得足夠大,以能存放任何班級的學生數據.顯然這將會浪費內存.鏈表則沒有這種缺點,它根據需要開辟內存單元.圖10.11表示最簡單的一種鏈表(單向鏈表)的結構.鏈表有一個"頭指針"變數,圖中以head表示,它存放一個地址.
該地址指向一個元素.鏈表中每一個元素稱為"結點",每個結點都應包括兩個部分:一為用戶需要用的實際數據,二為下一個結點的地址.課以看出,head指向第一個元素;第一個元素又指向第二個元素;……,直到最後一個元素,該元素不再指向其它元素,它稱為'表尾",它的地址部分放一個"NULL"(表示"空地址").鏈表到此結束.
可以看到:鏈表中各元素在內存中可以不是連續存放的.要找某一元素,必須先找到上一個元素,根據它提供的下一元素地址才能找到下一個元素.
如果不提供"頭指針"(head),則整個鏈表都無法訪問.鏈表如同一條鐵鏈一樣,一環扣一環,中間是不能斷開的.打個通俗的比方:幼兒園的老師帶領孩子出來散步,老師牽著第一個小孩的手,第一個小孩的另一隻手牽著第二個孩子,……,這就是一個"鏈",最後一個孩子有一隻手空著,他是"鏈尾".要找這個隊伍,必須先找到老師,然後順序找到每一個孩子.
可以看到,這種鏈表的數據結構,必須利用指針變數才能實現
.即:一個結點中應包含一個指針變數,用它存放下一結點的地址.
前面介紹了結構體變數,它包含若干成員.這些成員可以是數值類型,字元類型,數組類型,也可以是指針類型.這個指針類型可以是指向其它結構體類型數據,也可以指向它所在的結構體類型.例如:
struct student
{int num;
float score;
struct student *next;
next是成員名,它是指針類型的,它指向struct student類型數據(這就是next所在的結構體類型).用這種方法可以建立鏈表.見圖10.12.
其中每一個結點都屬於struct student類型,它的成員next存放下一結點的地址,程序設計人員可以不必具體知道地址值,
只要保證將下一個結點的地址放到前一結點的成員next中即可.
請注意:上面只是定義了一個struct student類型,並未實際分配存儲空間.前面講過,鏈表結構是動態地分配存儲的,即在需要時才開辟一個結點的存儲單元.怎樣動態地開辟和釋放存儲單元呢 C語言編譯系統的庫函數提供了以下有關函數.
1.malloc(size) 在內存的動態存儲區中分配一個長度為size的連續空間.
此函數的值(即"返回值")是一個指針,它的值是該分配域的起始地址.如果此函數未能成功地執行,則返回值為0.
2.calloc(n,size) 在內存的動態區存儲中分配n個長度為size的連續空間.函數返回分配域的起始地址;如果分配不成功,返回0.
3.free(ptr) 釋放由ptr指向的內存區.ptr是最近一次調用ca11或ma11oc函數時返回的值.
上面三個函數中,參數n和size為整型,ptr為字元型指針.
請注意:許多C版本提供的malloc和call0c函數得到的是指向字元型數據的指針.新標准C提供的ma110c和ca11oc函數規定為void*類型.
有了本節所介紹的初步知識,下面就可以對鏈表進行操作了(包括建立鏈表,插入或刪除鏈表中一個結點等).有些概念需要在後面的應用中逐步建立和掌握.
10.7.2建立鏈表
所謂建立鏈表是指從無到有地建立起一個鏈表,即一個一個地輸入各結點數據,並建立起前後相鏈的關系.下面通過一個例子來說明如何建立一個鏈表.
[例10.7]寫一函數建立一個有5名學生數據的單向鏈表.
先考慮實現此要求的演算法(見圖10. 13).
設三個指針變數:head,p1,p2,它們都指向結構體類型數據.先用mal1oc函數開辟一個結點,並使p1,p2指向它.
然後從鍵盤讀人一個學生的數據給pl所指的結點.我們約定學號不會為零,如果輸入的學號為0,則表示建立鏈表的過程完成,該結點不應連接到鏈表中.先使head的值為NULL(即等於0),這是鏈表為"空"時的情況(即head不指向任何結點,鏈表中無結點),以後增加一個結點就使head指向該結點.
如果輸入的pl一>num不等於0,而且輸入的是第一個結點數據(n=1)時,則令head=p1,
即把p1的值賦給head,也就是使head也指向新開辟的結點(圖10.14).P1所指向的新開辟的結點就成為鏈表中第一個結點.然後再開辟另一個結點並使p1指向它,接著讀入該結點的數據(見圖10.15(a)).如果輸入的p1->num!=0,則應鏈入第2個結點(n=2),由於n!=1,則將p1的值賦給p2-->next,也就是使第一個結點的next成員指向第二個結點(見圖10.15(b)).接著使p2=p1,
也就是使p2指向剛才建立的結點,見圖10.15(c).再開辟一個結點並使pl指向它,並讀入該結點的數據(見圖10.16(a)),在第三次循環中,由於n=3(n!=1),又將pl的值賦給p2一>next,也就是將第3個結點連接到第2個結點之後,並使p2=p1,使p2指向最後一個結點(見圖10.16(b).
再開辟一個新結點,並使pl指向它,
輸入該結點的數據(見圖10.17(a)).由於pl一>num的值為0,不再執行循環,此新結點不應被連接到鏈表中.此時將NULL賦給p2一>next,見圖10.17(b).建立鏈表過程至此結束,pl最後所指的結點未鏈入鏈表中,第3個結點的next成員的值為NULL,它不指向任何結點.雖然pl指向新開辟的結點,但從鏈表中無法找到該結點.
建立鏈表的函數可以如下:
#define NULL 0
#define LEN sizeof(struct student)
struct student
{1ong num;
float score;
struct student *next;
};
int n;
struct student *creat()
/*此函數帶回一個指向鏈表頭的指針*/
{struct student *head;
struct student *p1, *p2;
n=0;
p1=p2=(struct student*)mal1oc(LEN);/*開辟一個新單元*/
scanf("%ld,%f",&pl一>num,&pl一>score);
head=NULL:
while (pl一>num!=0)
{n=n十1;
if(n==1) head=pl;
else p2一>next=p1;
p2=pl;
pl=(struct student*)malloc(LEN);
scanf("%1d,%f",&p1-->num,&pl一>score);
}
p2一>next=NULL;
return(head);
}
請注意:
(1)第一行為#define命令行,令NULL代表0,用它表示"空地址".第二行令LEN代表struct student結構體類型數據的長度,
sizeof是"求位元組數運算符".
(2)第9行定義一個creat函數,它是指針類型,即此函數帶回一個指針值,它指向一個struct student類型數據.實際上此creat函數帶回一個鏈(3)malloc(LEN)的作用是開辟一個長度為LEN的內存區,LEN已定義為sizeof(struct student),即結構體struct student的長度.在一般系統中,malloc帶回的是指向字元型數據的指針.
而p1,p2是指向struct student類型數據的指針變數,二者所指的是不同類型的數據,這是不行的.因此必須用強制類型轉換的方法使之類型一致,在malloc (LEN)之前加了"(struct student*)",它的作用是使malloc返回的指針轉換為指向struct student類型數據的指針.注意"*"號不可省略,否則變成轉換成struct student類型了,而不是指針類型了.
(4)最後一行return後面的參數是head(head已定義為指針變數,指向struct student類型數據).因此函數返回的是head的值,也就是鏈表的頭地址.
(5)n是結點個數.
(6)這個演算法的思路是:讓pl指向新開的結點,p2指向鏈表中最後一個結點,把pl所指的結點連接在p2所指的結點後面,用"p2一>next=pl"來實現.
我們對建立鏈表過程作了比較詳細的介紹,
讀者如果對建立鏈表的過程比較清楚的話,對下面介紹的刪除和插入過程也就比較容易理解了.
10.7.3輸出鏈麥
將鏈表中各結點的數據依次輸出.這個問題比較容易處理.首先要知道鏈表頭元素的地址,也就是要知道head的值.然後設一個指針變數p,先指向第一個結點,輸出p所指的結點,然後使p後移一個結點,再輸出.直到鏈表的尾結點.
「例10.8]寫出輸出鏈表的函數print.
void print(head)
struct student *head;
{struct student *p;
printf("\nNow,These%drecords are:\n",n);
p=head;
if(head!=NULL)
do
{printf("%ld%5.1f\",p一>num,p—>score);
p=p一>next;
}while(p!=NULL);
演算法可用圖10.18表示.
其過程可用圖10.19表示.p先指向第一結點,在輸出完第一個結點之後,p移到圖中p'虛線位置,指向第二個結點.程序中p=p一>next的作用是:將p原來所指向的結點中next的值賦給p,
而p一>next的值就是第二個結點的起始地址.將它賦給p就是使p指向第二個結點.
head的值由實參傳過來,也就是將已有的鏈表的頭指針傳給被調用的函數,在print函數中從head所指的第一個結點出發順序輸出各個結點.
10.7.4 對鏈麥的刪除操作
已有一個鏈表,希望刪除其中某個結點.怎樣考慮此問題的演算法呢,先打個比方:
一隊小孩(A.B.C.D.E)手拉手,如果某一小孩(C)想離隊有事,而隊形仍保持不變.只要將C的手從兩邊脫開,B改為與D拉手即可,見圖10.20.圖10.20(a)是原來的隊伍,圖10.20(b)是c離隊後的隊伍.
與此相仿,從一個鏈表中刪去一個結點,並不是真正從內存中把它抹掉,而是把它從鏈表中分離開來,即改變鏈接關系即可.
[例10.9]寫一函數以刪除指定的結點.
我們以指定的學號作為刪除結點的標志.例如,輸入89103表示要求刪除學號為89103的結點.解題的思路是這樣的:從p指向的第一個結點開始,檢查該結點中的num值是否等於輸入的要求刪除的那個學號.如果相等就將該結點刪除,如不相等,就將p後移一個結點,再如此�下去,直到遇到表尾為止.
可以設兩個指針變數pl和p2,先使pl指向第一個結點(圖10.21(a)).如果要刪除的不是第一個結點,
則使pl後指向下一個結點(將pl一>next賦給pl),在此之前應將pl的值賦給p2,使p2指向剛才檢查過的那個結點,見圖10.21(b).如此一次一次地使p後移,直到找到所要刪除的結點或檢查完全部鏈表都找不到要刪除的結點為止.如果找到某一結點是要刪除的結點,還要區分兩種情況:①要刪的是第一個結點(pl的值等於head的值,如圖10.21(a)那樣),則應將pl一>next賦給head.見圖10.21(c).
這時head指向原來第二個結點.第一個結點雖然仍存在,但它已與鏈表脫離,因為鏈表中沒有一個元素或頭指針指向它.雖然p1還指向它,它仍指向第二個結點,但仍無濟於事,現在鏈表的第一個結點是原來第二個結點,原來第一個結點"丟失".②如果要刪除的不是第一個結點,則將pl一>next賦給p2一>next,見圖10.21(d).p2一>next原來指向pl指向的結點(圖中第二個結點),現在p2一>next改為指向p1一>next所指向的結點
(圖中第三個結點).pl所指向的結點不再是鏈表的一部分.
還需要考慮鏈表是空表(無結點)和鏈表中找不到要刪除的結點的情況.
圖10.22表示解此題的演算法.
刪除結點的函數del如下:
struct student *del(head,num)
struct student *head;
1ong num;
{struct student *p1,*p2;
if(head==NULL) {printf("\nlist null!\n");goto end;}
p1=head;
whi1e (num!=pl一>num&&pl一>next!一NULL)/*pl指向的不是所要找的結點,並且後面還有結點點*/
{p2=p1;pl=pl一>next;}/*後移一個結點*/
if (num==pl一>num) /*找到了*/
{if (n1==head) head=pl一>next;/*若pl指向的是頭結點,把第二個結點地址賦予head*/
e1se p2一>next=pl一>next;/*否則將下一結點地址賦給前一結點地址*\
printf("delete:%ld\n",num);
n=n-1;
}
else printf("%ld not been found!\n",num);/*找不到該結點*/
end:
return(head);
}
函數的類型是指向struct student類型數據的指針,
它的值是鏈表的頭指針.函數參數為head和要刪除的學號num.head的值可能在函數執行過程中被改變(當刪除第一個結點時).
10.7.5對鏈表的插入操作
將一個結點插入到一個已有的鏈表中.設已有的鏈表中各結點中的成員項num(學號)是按學號由小到大順序排列的.
用指針變數p0指向待插入的結點,pl指向第一個結點.見圖10.23(a).
將p0一>num與pl一>num相比較,如果p0一>num>pl一>num,則待插入的結點不應插在pl所指的結點之前.此時將pl後移,並使p2指向剛才pl所指的結點,見圖10.23(b).再將p1一>num與p0一>num比.如果仍然是p0一>num大,則應使pl繼續後移,直到p0一>numnum為止.這時將p0所指的結點插到pl所指結點之前.但是如果p1所指的已是表尾結點,則pl就不應後移了.如果p0一>num比所有結點的num都大,
則應將p0所指的結點插到鏈表末尾.
如果插入的位置既不在第一個結點之前,又不在表尾結點之後,則將p0的值賦給p2一>next,即使p2一>next指向待插入的結點,然後將pl的值賦給p0->next,即使得p0一>next指向pl指向的變數.見圖10.23(c).可以看到,在第一個結點和第二個結點之間已插入了一個新的結點.
如果插入位置為第一結點之前(即pl等於head時),
則將p0賦給head,將p1賦給p0->next.見圖10.23(d).如果要插到表尾之後,應將p0賦給pl一>next,NULL賦給p0一>next,見圖10.23(e).
以上演算法可用圖10.24表示.
[例10. 10]插入結點的函數insert如下.
struct student *insert(head,stud)
struct student *head,*stud:
{struct student *p0,*p1,*p2;
pl=head;/*使pl指向第一個結點*/
p0=stud;/*p0指向要插入的結點*/
if (head==NULL)/*原來是空表*/
{head=p0;p0一>next=NULL;}/*使p0指向的結點作為第一個結點*/
else
{while ((p0一>num>pl一>num)&&(pl一>next!=NULL))
{p2=p1;p1=pl一>next;}/*p2指向剛才pl指向的結點,p1後移一個結點*/
if(p0->numnext=p0;/*插到p2指向的結點之後*/
p0—>next=p1;}
else
{pl一>next=p0;p0一>next=NULL;}}/*插到最後的結點之後*/
n=n+1; /*結點數加1*/
return(head);
}
函數參數是head和stud.stud也是一個指針變數,從實參傳來待插入結點的地址給stud.語句p0=stud的作用是使p0指向待插入的結點.
函數類型是指針類型,函數值是鏈表起始地址head.
將以上建立,輸出,刪除,插入的函數組織在一個程序中,用main函數作主調函數.可以寫出以下main函數.
main()
{struct student *head,stu;
1ong de1_num;
printf("input records:\n");
head=creat(); /*返回頭指針*/
print(head); /*輸出全部結點*/
printf("\ninput the deleted 0number:");
scanf("%ld",&de1_mum);/*輸入要刪除的學號*/
head=del(head,de1_num);/*刪除後的頭地址*/
print(head); /*輸出全部結點*/
prinif("/ninput the inserted record:")/*輸入要插入的記錄*/
scanf("%ld,%f",&stu.num,&stu.score);
head=insert(head,&stu);/*返回地址*/
print(head);
}
此程序運行結果是正確的.
它只刪除一個結點,插入一個結點.但如果想再插入一個結點,重復寫上程序最後四行,即共插入兩個結點.運行結果卻是錯誤的.
input records:(建立鏈表)
89101,90
89103,98
89105,76
0,0
Now,These 3 records are:
89101 90.0
89103 98.0
89105 76.0
inpu the deleted number:
89103 (刪除)
delete:89103
Now,These 2 records are:
89101 90.0 89105 76.0
input the inserted record:89102
90 (插入第一個結點)
Now,These 3 records are:
89101 90.0
89102 90.0
89105 76.0
input the inserted record:89104,99/(插入第二個結點)
Now,The 4 records are:
89101 90.0
89104 99.0
89104 99.0
89104 99.0
...
...
(無終止地輸出89104的結點數據)
請讀者將main與insert函數結合起來考察為什麼會產生以上運行結果.
出現以上結果的原因是:stu是一個有固定地址的變數.第一次把stu結點插入到鏈表中.第二次若再用它來插入第二個結點,就把第一次結點的數據沖掉了.
實際上並沒有開辟兩個結點.讀者可根據insert函數畫出此時鏈表的情況.為了解決這個問題,必須在每插入一個結點時新開辟一個內存區.我們修改main函數,使之能刪除多個結點(直到輸入要刪的學號為0),能插入多個結點(直到輸入要插入的學號為0).
main函數如下:
main()
{struct student *head,*stu;
1ong de1_num;
printf("input records:/n");
head=creat();
print (head);
printf("/ninput the deleted number:");
scanf("%1d",&del_num);
while (de1_num!=0)
{head=del(head,del_num);
print(head);
printf("input the deleted number:");
scanf("%ld",&del_num);
printf("\ninput the inserted record:");
stu=(struct student*)malloc(LEN);
scanf("%1d,%f,",&stu一>num,&stu一>scor);
while (stu一>num!=0)
{head=insert(head,stu):
print(head);
prinif("input the inserted record:");
stu=(struct student*)malloc(LEN);
scanf("%1d,%f,&stu一>num,&stu一>score);
}
}
sum定義為指針變數,在需要插入時先用malloc函數開辟一個內存區,將其起始地址經強制類型轉換後賦給stu,然後輸入此結構體變數中各成員的值.對不同的插入對象,stu的值是不同的,每次指向一個新的結構體變數.在調用insert函數時,實參為head和stu,將已建立的鏈表起始地址傳給insert函數的形參,將stu(既新開辟的單元的地址)傳給形參stud,函數值返回經過插入之後的鏈表的頭指針(地址).
運行情況如下:
input records:
89101,99
89103,87
89105,77
0,0
Now, These 3 records are.
89101 99.0
89103 87.0
89105 77.0
input the deleted number:89103
delete:89103
Now,These 2 records are:
89101 99.0
89105 77.0
input the de1eted number:89105
delete:89105
Now,These l records are:
89101 99.0
input the de1eted number:0
1nput the inserted record:89104,87
NOw,These 2 records are:
89101 99.0
89104 87.0
input the inserted record:89106,65
Now,These 3 records are:
89101 99.0
89104 87.0
89106 65.0
input the inserted record:0,0
對這個程序請讀者仔細消化.
指針的應用領域很寬廣,除了單向鏈表之外,還有環形鏈表,雙向鏈表.此外還有隊列,樹,棧,圖等數據結構.
有關這些問題的演算法可以學習《數據結構>>課程,在此不作詳述.
⑻ C語言中怎麼定義鏈表,最好把各個代碼都詳細的解釋一下!
/*creat
a
list*/
#include
"stdlib.h"
#include
"stdio.h"
struct
list
{
int
data;
struct
list
*next;
};
typedef
struct
list
node;
typedef
node
*link;
void
main()
{
link
ptr,head;
int
num,i;
ptr=(link)malloc(sizeof(node));
ptr=head;
printf("please
input
5
numbers==>\n");
for(i=0;i<=4;i++)
{
scanf("%d",&num);
ptr->data=num;
ptr->next=(link)malloc(sizeof(node));
if(i==4)
ptr->next=NULL;
else
ptr=ptr->next;
}
ptr=head;
while(ptr!=NULL)
{
printf("The
value
is
==>%d\n",ptr->data);
ptr=ptr->next;
}
}
上面是一個簡單的創建鏈表的C程序。所謂鏈表形象的講就是一個數據塊裡面存有數據,並且存有下一個數據的指針,這樣一個指一個形成一個數據鏈。這個數據鏈可以被操作,例如插入數據,刪除數據,等。至於指令,首先定義一個結構體,它存有數據和指向下一個數據塊的指針。然後分配空間。注意最後一個為NULL,當然你也可以指向開頭一個數據塊形成一個循環鏈表。
⑼ c語言程序設計 用鏈表編寫商品庫存管理。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node{
char no[20];//存放編號
char name[40];//存放名稱
int reserve;//庫存
struct node *next;
}NODE;
typedef struct link{
NODE *front;//頭指針
NODE *rear;//尾指針
}LINK;
NODE *create_node(void){
NODE *node = (NODE *)malloc(sizeof(NODE));
printf("請輸入貨物編號:");
gets(node->no);
printf("請輸入貨物名稱:");
gets(node->name);
printf("請輸入貨物名稱:");
char ch;
while( (ch= getchar()) != '\n');//rewind(stdin);
scanf("%d",&node->reserve);
node->next = NULL;
return node;
}
void init_link(LINK *link){
link->rear = NULL;
link->front = NULL;
}
int link_empty(LINK *link){
return link->front == NULL ? 1: 0;
}
int node_num(LINK *link){
int num = 0;
if( link_empty(link)){
return num;
}
num = 1;
NODE *node = link->front;
while(node != link->rear){
node = node->next;
++num;
}
return num;
}
/*NODE *node_find(LINK *link,const int n){
int num = node_num(link);
if(num < n){
printf("公有節點%d個,無法找到第%d個節點\n",num,n);
}
else{
}
}
*/
void node_push(LINK *link){
NODE *node = create_node();
if(link->front == NULL){
link->front = node;
link->rear = node;
node->next = NULL;
}
else{
link->rear->next = node;
link->rear = node;
node->next = NULL;
}
}
void node_insert(LINK *link,const int n){
int num = 0,i = 1;
NODE *node = link->front;
NODE *new_node = NULL;
if ( link_empty(link) ){
printf("鏈表為空,將建立鏈表!\n");
node_push(link);
}
else{
if( n <= 1){
printf("在鏈表頭插入數據\n");
new_node = create_node();
new_node->next = link->front;
link->front = new_node;
}
else if( n>= num = node_num(link) ){
printf("節點數少於%d,將在末尾插入節點.\n",n);
node_push(link);
}
else{
printf("在第n個節點後插入數據\n");
if(num >= n){
while( i != n){
node = node->next;
++i;
}
new_node = create_node();
new_node-next = node->next;
node->next = new_node;
}
}
}
void find_node_insert(LIKNK *link,const char *name){
NODE *node = link->front;
if( link_empty(link) )
node_push(link);
else {
while(strcmp(node->name,name) != 0){
if(node != link->rear)
node = node->next;
else break;
}
if(node != NULL){
NODE *new_node = create_node();
new_node-next = node->next;
node->next = new_node;
}
else {
printf("沒有找到相關貨物,將在頭節點插入數據\n");
intsert(link,0);
}
}
/*由於我不知到你對貨物統計具體實現的要求,關於貨物數量統計就你自己寫了,應該比較簡單。*/
/* 代碼沒有具體運行過,如果你學過C結構體與指針,就這個代碼思路應該看得明白,真正的實現你自己實現吧
這樣對你會更好寫。可能會有錯誤的地方,請謹慎。 */