1. 一道c語言鏈表問題
#include
#include
#define
NULL
0
#define
LEN
sizeof(struct
student)
struct
student
{
long
num;
/*學號*/
float
score;
/*分數,其他信息可以繼續在下面增加欄位*/
struct
student
*next;
/*指向下一節點的指針*/
};
int
n;
/*節點總數*/
/*
==========================
功能:創建節點
返回:指向鏈表表頭的指針
==========================
*/
struct
student
*Create()
{
struct
student
*head;
/*頭節點*/
struct
student
*p1=NULL;
/*p1保存創建的新節點的地址*/
struct
student
*p2=NULL;
/*p2保存原鏈表最後一個節點的地址*/
n
=
0;
/*創建前鏈表的節點總數為0:空鏈表*/
p1
=
(struct
student
*)malloc(LEN);
/*開辟一個新節點*/
p2
=
p1;
/*如果節點開辟成功,則p2先把它的指針保存下來以備後用*/
if
(p1
==
NULL)
/*節點開辟不成功*/
{
printf("\nCann't
create
it,
try
it
again
in
a
moment!\n");
return
NULL;
}
else
/*節點開辟成功*/
{
head
=
NULL;
/*開始head指向NULL*/
printf("Please
input
%d
node
--
num,score:
",n+1);
scanf("%ld,%f",&(p1->num),&(p1->score));
/*錄入數據*/
}
while(p1->num
!=
0)
/*只要學號不為0,就繼續錄入下一個節點*/
{
n
+=
1;
/*節點總數增加1個*/
if
(n==1)
/*如果節點總數是1,則head指向剛創建的節點p1*/
{
head
=
p1;
/*
注意:
此時的p2就是p1,也就是p1->next指向NULL。
這樣寫目的是與下面else保持一致。
*/
p2->next
=
NULL;
}
else
{
p2->next
=
p1;
/*指向上次下面剛開辟的節點*/
}
p2
=
p1;
/*把p1的地址給p2保留,然後p1去產生新節點*/
p1
=
(struct
student
*)malloc(LEN);
printf("Please
input
%d
node
--
num,score:
",n+1);
scanf("%ld,%f",&(p1->num),&(p1->score));
}
p2->next
=
NULL;
/*此句就是根據單向鏈表的最後一個節點要指向NULL*/
free(p1);
/*釋放p1。用malloc()、calloc()的變數都要free()*/
p1
=
NULL;
/*特別不要忘記把釋放的變數清空置為NULL,否則就變成"野指針",即地址不確定的指針。*/
return
head;
/*返回創建鏈表的頭指針*/
}
/*
===========================
功能:輸出節點
返回:
void
===========================
*/
void
Print(struct
student
*head)
{
struct
student
*p;
printf("\nNow
,
These
%d
records
are:\n",n);
p
=
head;
if(head
!=
NULL)
/*只要不是空鏈表,就輸出鏈表中所有節點*/
{
printf("head
is
%o\n",
head);
/*輸出頭指針指向的地址*/
do
{
/*
輸出相應的值:當前節點地址、各欄位值、當前節點的下一節點地址。
這樣輸出便於讀者形象看到一個單向鏈表在計算機中的存儲結構,和我們
設計的圖示是一模一樣的。
*/
printf("%o
%ld
%5.1f
%o\n",
p,
p->num,
p->score,
p->next);
p
=
p->next;
/*移到下一個節點*/
}
while
(p
!=
NULL);
}
}
/*
==========================
功能:刪除指定節點
(此例中是刪除指定學號的節點)
返回:指向鏈表表頭的指針
==========================
*/
/*
單向鏈表的刪除圖示:
---->[NULL]
head
圖3:空鏈表
從圖3可知,空鏈表顯然不能刪除
---->[1]---->[2]...---->[n]---->[NULL](原鏈表)
head
1->next
2->next
n->next
---->[2]...---->[n]---->[NULL](刪除後鏈表)
head
2->next
n->next
圖4:有N個節點的鏈表,刪除第一個節點
結合原鏈表和刪除後的鏈表,就很容易寫出相應的代碼。操作方法如下:
1、你要明白head就是第1個節點,head->next就是第2個節點;
2、刪除後head指向第2個節點,就是讓head=head->next,OK這樣就行了。
---->[1]---->[2]---->[3]...---->[n]---->[NULL](原鏈表)
head
1->next
2->next
3->next
n->next
---->[1]---->[3]...---->[n]---->[NULL](刪除後鏈表)
head
1->next
3->next
n->next
圖5:有N個節點的鏈表,刪除中間一個(這里圖示刪除第2個)
結合原鏈表和刪除後的鏈表,就很容易寫出相應的代碼。操作方法如下:
1、你要明白head就是第1個節點,1->next就是第2個節點,2->next就是第3個節點;
2、刪除後2,1指向第3個節點,就是讓1->next=2->next。
*/
struct
student
*Del(struct
student
*head,
long
num)
{
struct
student
*p1;
/*p1保存當前需要檢查的節點的地址*/
struct
student
*p2;
/*p2保存當前檢查過的節點的地址*/
if
(head
==
NULL)
/*是空鏈表(結合圖3理解)*/
{
printf("\nList
is
null!\n");
return
head;
}
/*定位要刪除的節點*/
p1
=
head;
while
(p1->num
!=
num
&&
p1->next
!=
NULL)
/*p1指向的節點不是所要查找的,並且它不是最後一個節點,就繼續往下找*/
{
p2
=
p1;
/*保存當前節點的地址*/
p1
=
p1->next;
/*後移一個節點*/
}
if
(num
==
p1->num)
/*找到了。(結合圖4、5理解)*/
{
if
(p1
==
head)
/*如果要刪除的節點是第一個節點*/
{
head
=
p1->next;
/*頭指針指向第一個節點的後一個節點,也就是第二個節點。這樣第一個節點就不在鏈表中,即刪除。*/
}
else
/*如果是其它節點,則讓原來指向當前節點的指針,指向它的下一個節點,完成刪除*/
{
p2->next
=
p1->next;
}
free(p1);
/*釋放當前節點*/
p1
=
NULL;
printf("\ndelete
%ld
success!\n",num);
n
-=
1;
/*節點總數減1個*/
}
else
/*沒有找到*/
{
printf("\n%ld
not
been
found!\n",num);
}
return
head;
}
/*
==========================
功能:插入指定節點的後面
(此例中是指定學號的節點)
返回:指向鏈表表頭的指針
==========================
*/
/*
單向鏈表的插入圖示:
---->[NULL](原鏈表)
head
---->[1]---->[NULL](插入後的鏈表)
head
1->next
圖7
空鏈表插入一個節點
結合原鏈表和插入後的鏈表,就很容易寫出相應的代碼。操作方法如下:
1、你要明白空鏈表head指向NULL就是head=NULL;
2、插入後head指向第1個節點,就是讓head=1,1->next=NULL,OK這樣就行了。
---->[1]---->[2]---->[3]...---->[n]---->[NULL](原鏈表)
head
1->next
2->next
3->next
n->next
---->[1]---->[2]---->[x]---->[3]...---->[n]---->[NULL](插入後的鏈表)
head
1->next
2->next
x->next
3->next
n->next
圖8:有N個節點的鏈表,插入一個節點(這里圖示插入第2個後面)
結合原鏈表和插入後的鏈表,就很容易寫出相應的代碼。操作方法如下:
1、你要明白原1->next就是節點2,2->next就是節點3;
2、插入後x指向第3個節點,2指向x,就是讓x->next=2->next,1->next=x。
*/
struct
student
*Insert(struct
student
*head,
long
num,
struct
student
*node)
{
struct
student
*p1;
/*p1保存當前需要檢查的節點的地址*/
if
(head
==
NULL)
/*(結合圖示7理解)*/
{
head
=
node;
node->next
=
NULL;
n
+=
1;
return
head;
}
p1
=
head;
while
(p1->num
!=
num
&&
p1->next
!=
NULL)
/*p1指向的節點不是所要查找的,並且它不是最後一個節點,繼續往下找*/
{
p1
=
p1->next;
/*後移一個節點*/
}
if
(num
==
p1->num)
/*找到了(結合圖示8理解)*/
{
node->next
=
p1->next;
/*顯然node的下一節點是原p1的next*/
p1->next
=
node;
/*插入後,原p1的下一節點就是要插入的node*/
n
+=
1;
/*節點總數增加1個*/
}
else
{
printf("\n%ld
not
been
found!\n",num);
}
return
head;
}
/*
==========================
功能:反序節點
(鏈表的頭變成鏈表的尾,鏈表的尾變成頭)
返回:指向鏈表表頭的指針
==========================
*/
/*
單向鏈表的反序圖示:
---->[1]---->[2]---->[3]...---->[n]---->[NULL](原鏈表)
head
1->next
2->next
3->next
n->next
[NULL]next
2->next
3->next
n->next
head
圖9:有N個節點的鏈表反序
結合原鏈表和插入後的鏈表,就很容易寫出相應的代碼。操作方法如下:
1、我們需要一個讀原鏈表的指針p2,存反序鏈表的p1=NULL(剛好最後一個節點的next為NULL),還有一個臨時存儲變數p;
2、p2在原鏈表中讀出一個節點,我們就把它放到p1中,p就是用來處理節點放置順序的問題;
3、比如,現在我們取得一個2,為了我們繼續往下取節點,我們必須保存它的next值,由原鏈表可知p=2->next;
4、然後由反序後的鏈表可知,反序後2->next要指向1,則2->next=1;
5、好了,現在已經反序一個節點,接著處理下一個節點就需要保存此時的信息:
p1變成剛剛加入的2,即p1=2;p2要變成它的下一節點,就是上面我們保存的p,即p2=p。
*/
struct
student
*Reverse(struct
student
*head)
{
struct
student
*p;
/*臨時存儲*/
struct
student
*p1;
/*存儲返回結果*/
struct
student
*p2;
/*源結果節點一個一個取*/
p1
=
NULL;
/*開始顛倒時,已顛倒的部分為空*/
p2
=
head;
/*p2指向鏈表的頭節點*/
while
(p2
!=
NULL)
{
p
=
p2->next;
p2->next
=
p1;
p1
=
p2;
p2
=
p;
}
head
=
p1;
return
head;
}
/*
以上函數的測試程序:
提示:根據測試函數的不同注釋相應的程序段,這也是一種測試方法。
*/
main()
{
struct
student
*head;
struct
student
*stu;
long
thenumber;
/*
測試Create()、Print()*/
head
=
Create();
Print(head);
/*測試Del():請編譯時去掉注釋塊*/
/*
printf("\nWhich
one
delete:
");
scanf("%ld",&thenumber);
head
=
Del(head,thenumber);
Print(head);
*/
/*測試Insert():請編譯時去掉注釋塊*/
/*
stu
=
(struct
student
*)malloc(LEN);
printf("\nPlease
input
insert
node
--
num,score:
");
scanf("%ld,%f",&stu->num,&stu->score);
printf("\nInsert
behind
num:
");
scanf("%ld",&thenumber);
head
=
Insert(head,thenumber,stu);
free(stu);
stu
=
NULL;
Print(head);
*/
/*測試Reverse():請編譯時去掉注釋塊*/
/*
head
=
Reverse(head);
Print(head);
*/
printf("\n");
system("pause");
}
2. c語言鏈表看不懂,while語句後邊開始,求幫助,最好有示意圖配解釋,謝謝謝謝
這就是個頭插法建立鏈表的代碼,不過寫的不好!
structStudent*head,*new;
head=NULL;
new=malloc();
scanf("%s",new->name);
scanf("%d",&new->number);
while(new->number!=0)//當輸入的number值不為0時循環
{
new->next=head;//新結點的後繼指向head你就當head是一個鏈表的頭,後面有很多數據結點
head=new;//新結點成為新的head,這樣一個一個的就串起來了!
new=malloc();//繼續申請結點
scanf("%s",new->name);//讀入數據
scanf("%d",&new->number);
}
不知道你看的是哪裡的書,程序寫的真不咋地
3. 講這個c語言while(NULL!=p->next)翻譯成中文
默認:指針p指向一個含有next指針變數的結構,並且next指針和p指針的類型一致,一般用於鏈表結構指向下一個鏈表節點。
當p指針指向的結構中next變數不為NULL時循環
換句話說,如果是在鏈表中,當p指向節點的後續節點存在時繼續循環,當沒有後續節點時停止循環。
4. C語言鏈表輸出,while(p)是什麼意思怎麼判斷完成輸入了
while(p)
等價於
while(p!=NULL)
如果p不指向NULL,那麼就是沒有到達結尾,那麼就執行循環體中的printf()
5. 關於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的值,應該就可以了。
6. 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,當然你也可以指向開頭一個數據塊形成一個循環鏈表。
7. C語言結構體鏈表逆置中這個代碼的while循環什麼時候終止
盡管程序不全,沒有看到pa變數的類型,但是,仍然可以判定當pa變數的值為0時while循環終止。
在c語言中,常量NULL的值就是0。也就是說,當pa的值是NULL時,循環就終止了。
有什麼問題請留言
8. 用C語言實現鏈表的演算法
這個是我們數據結構上機實驗的鏈表問題,
#include<stdio.h>
#include<malloc.h>
#define
LEN
sizeof(LinkNode)
typedef
int
Datatype;
typedef
int
Status;
typedef
struct
LinkNode{
Datatype
data;
struct
LinkNode
*next;
}
LinkNode,*LinkList;
typedef
struct
OrderedList
{
LinkNode
*head,*tail;
int
Listsize;
}
OrderedList;//有序循環鏈表的頭節點head,尾接接節點
tail及長度Listsize
Status
InitList(OrderedList
*List)//生成循環鏈表頭節點
{
List->tail=List->head=(LinkList)malloc(LEN);
if(List->head==NULL)
return
0;
else
{
List->head->next=List->tail;
List->tail->next=List->head;
List->Listsize=0;
return
1;
}
}
void
OrderedInsert(OrderedList
*List,Datatype
data)//每調用一次有序插入data形成有序的(從小到大)的鏈表
{
LinkNode
*p
,*q;
if(List->head==List->tail->next)
{
p=(LinkNode*)malloc(LEN);
p->data
=
data;
List->head->next=p;
p->next=List->tail;
List->Listsize++;
}
else
{
p=List->head->next;
q
=
List->head;
while(p->data<data&&p!=List->tail)
{
q
=
p;
p=p->next;
}
if(p->data==data)
{printf("YOu
have
input
the
same
datas
%d\n\t
YOu
should
input
another
data
\n",data);
scanf("%d",&data);
OrderedInsert(List,data);
}
else
{
p=(LinkNode*)malloc(LEN);
p->data
=
data;
p->next
=
q->next;
q->next
=
p;
List->Listsize++;
}
}
}
void
Creatset(OrderedList
*List)//多次調用OrderedInsert()生成有序鏈表即集合List
{
Datatype
data;
int
setsize
,
i=0;
printf("Please
input
the
setsize
you
want
to
creat:\n");
scanf("%d",&setsize);
InitList(List);
if(setsize==0)
printf("You
needen't
input
any
data\n");
else
if(setsize==1)
printf("Please
input
a
single
data\n");
else
printf("Please
input
%d
different
datas;\n",setsize);
while(i<setsize||setsize>List->Listsize)//當循環次數i小於setsize或者集合內實際元素數List.Listsize小於setsize時一直循環下去
{
scanf("%d",&data);
OrderedInsert(List,data);
i++;
}
}
void
Append(OrderedList
*List,Datatype
data)//在循環鏈表的最後面追加
一個data
{
LinkNode
*p;
p=(LinkNode*)malloc(LEN);
p->data=data;
List->tail=List->tail->next=p;
List->tail->next=List->head;
List->Listsize+=1;
}
void
MergeList(OrderedList
La,OrderedList
Lb,OrderedList
*Lc)//有序循環鏈表ListLa,ListLb求並集生成ListLc
{
LinkList
Pa,Pb;
Pa=La.head->next;Pb=Lb.head->next;
while(Pa!=La.tail&&Pb!=Lb.tail)
{
if(Pa->data<=Pb->data)
{
Append(Lc,Pa->data);
Pa=Pa->next;
}
else
{
Append(Lc,Pb->data);Pb=Pb->next;
}
}
while(Pa!=La.tail)
{
Append(
Lc,Pa->data);Pa=Pa->next;}
while(Pb!=Lb.tail)
{
Append(Lc,Pb->data);Pb=Pb->next;}
}
void
Print(OrderedList
List)
{
LinkNode
*p;
p=List.head->next;
if(p->next==List.head)
printf("No
Elem\n");
while(p!=List.head)
{
printf("%5d",p->data);p=p->next;
}
printf("\n");
}
void
main()
{
OrderedList
ListLa,ListLb,ListLc;
Creatset(&ListLa);
Creatset(&ListLb);
InitList(&ListLc);
MergeList(ListLa,ListLb,&ListLc);
printf("The
orgnial
list
ListLa,ListLb:\n");
Print(ListLa);
Print(ListLb);
printf("The
Merge
list
ListLc;\n");
Print(ListLc);
}
9. c語言中if和while 有什麼區別
區別:
一、if和while共同點是都有判斷。
二、if和while不同點是,if後的語句只執行一次,while則會循環執行,直到出現while後的條件成才退出。
三、語法不同:
1、IF(logical_test,value_if_true,value_if_false)
2、while<條件>do<語句>
意為當條件符合時,接著做下面的語句;不符合時,退出循環。
四、功能不同:
1、IF函數是條件判斷函數:如果指定條件的計算結果為TRUE,IF函數將返回某個值;如果該條件的計算結果為FALSE,則返回另一個值。
例如IF(測試條件,結果1,結果2),即如果滿足「測試條件」則顯示「結果1」,如果不滿足「測試條件」則顯示「結果2」。
2、while循環也被稱為「當」型循環。即當條件為真時,執行循環體中。在R語言中,while循環的語法格式如下:while(cond){expr}其中,cond是一個邏輯條件表達式,其值應為TRUE或FALSE;expr是循環體中的語句,即當cond條件為TRUE時要執行的表達式或若干語句。
例如:
1、if用來做條件判斷
if用來做條件判斷,與else搭配使用。在if條件判斷中,若邏輯條件表達式為真,則運行語句或語句塊;如果邏輯條件表達式為假,則跳過語句;
例如,超過五點下班走人,否則就繼續上班。在這里&ldquo;時間&rdquo;就是判斷條件,時間就是下班或者上班只要時間超過五點,即判斷條件為真,則執行的事件就是下班,else語句不再執行,即不再執行上班語句;只要事件沒有超過五點,則執行上班語句。
2、while是循環語句
在C語言中通常用while來表示循環,例如在main()函數中一般都用while(1)來讓主程序循環執行。即在邏輯條件表達式為真的情況下,while反復執行循環體內包含的語句或語句塊,直到條件不成立。
例如:天氣如果是下雨就執行睡覺指令,直到不下雨為止;如陰天、晴天或者下雪等其他天氣就不執行睡覺指令。
4、if語句叫做選擇語句,一般和else一起使用。判斷條件是否成立,成立則執行if後面的分支,不成立則執行else後面的分支。執行完畢則轉入下條語句。
while語句叫做循環語句。同樣是判斷條件是否成立。但是執行完畢後繼續判斷該條件,直到該條件不成立則轉入下一條語句。
對於一個假條件,兩者的執行情況是一致的。對於一個真條件,執行完畢後if語句就順序執行下一條,while還要繼續判斷和執行。這就是兩者的不同吧。
對於while語句,必須要在執行語句中設置改變判斷條件結果的語句或者設置跳出語句以避免陷入死循環。