很納悶,上次發的fifteen竟然說包含不適內容,就是程序而已啊,莫名其妙。
這個就是公開課上鍊表的程序,稍微改了下,沒用他的頭文件,同時添加了註釋。用codeblocks編譯通過。
鏈表這個確實挺麻煩,並不是不能理解,而是具體實施該怎麼做。
主要要理解頭指針,頭節點,第一個節點的含義和怎麼表示。
下面是程序:
/*
一個數字鏈表。可以實現插入(按大小),查詢,刪除等功能
輸入1,用於刪除;
輸入2,用於尋找;
輸入3,用於插入;
輸入4,用於遍歷;
輸入0,用於退出;
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//定義鏈表
typedef struct node
{
int n;//注意這個n,和平時int n區別開來
struct node *next;
}
node;
//頭指針
node *first=NULL;
//聲明函數
void delete(void);
void find(void);
void insert(void);
void traverse(void);
int getint(void);//代替頭文件裏的GetInt
//主函數
int
main()
{
int c;
do
{
printf("\n菜單\n\n"
"輸入1,刪除鏈表內數字\n"
"輸入2,尋找鏈表內數字\n"
"輸入3,插入數字到鏈表中(自動排序)\n"
"輸入4,遍歷鏈表\n"
"輸入0,退出\n");
//輸入
printf("請輸入命令:");
c=getint();
//分類
switch(c)
{
case 1:delete();break;
case 2:find();break;
case 3:insert();break;
case 4:traverse();break;
default:printf("請按照提示輸入命令\n");
}
}
while(c!=0);
//釋放鏈表空間
node *ptr=first;
while(ptr!=NULL)
{
node *predptr=ptr;
ptr=ptr->next;
free(predptr);
}
return 0;
}
//getint
int getint(void)
{
int p,m,num;
while(1)
{
p=scanf("%d",&num);//scanf的返回值
while((m=getchar())!='\n'&&m!=EOF);//清除輸入緩存
if(p==1)//返回值是數字則爲1,否則是其它的
return num;
else
printf("請確保輸入的是整數,再試一次:");
}
}
//delete
void
delete(void)
{
printf("輸入要刪除的數字:");
int n=getint();
node *ptr=first;//爲什麼不直接用first
node *predptr=NULL;//
while(ptr!=NULL)//最後節點
{
if(ptr->n==n)//鏈表裏面有這個數,這2個n是不一樣的,一個是定義鏈表裏的數據,一個是輸入的數字
{
//if(ptr->n==first->n)
if(ptr==first)//ptr是在變化的,因爲是個while循環,判斷ptr變化了沒?用這個if(ptr->n==first->n)可以不?實驗後可以
{
first=ptr->next;
free(ptr);
}
else//在中間或是尾部
{
predptr->next=ptr->next;//predptr在這裏已經不是NULL了,第一個節點不相等就會執行下面的predptr=ptr;而相等就不會進行這一步
free(ptr);
}
break;
}
else
{
predptr=ptr;
ptr=ptr->next;//同上面聯繫起來看,predptr與ptr相隔1個節點
}
}
if(ptr==NULL)
printf("你所要刪除的數字不存在\n");
traverse();
}
//insert
void
insert(void)
{
node *newptr=malloc(sizeof(node));
if(newptr==NULL)
{
printf("申請空間出錯\n");
return;
}
printf("輸入插入的數字:");
//插入的鏈表節點
newptr->n=getint();
newptr->next=NULL;
//如果鏈表是空的,則直接是newptr
if(first==NULL)
first=newptr;//爲什麼不是first->next=newptr?因爲first單純是個指針,就是第一個節點,first->next是第二個節點了。
//插入鏈表頭部
else if(newptr->n<first->n)//first->n?第一個數據?
{
newptr->next=first;//爲什麼不是first->next?同上,相當於將newptr和first鏈接起來
first=newptr;
}
//插入中間或底部
else
{
node *predptr=first;//爲什麼不直接用first而是新建一個指針predptr呢?
while(1)
{
//是否重複
if(predptr->n==newptr->n)
{
free(newptr);
break;
}
//判斷是否在尾部
else if(predptr->next==NULL)
{
predptr->next=newptr;
break;
}
//在中間的情況
else if(predptr->next->n>newptr->n)//predptr->next->n?
{
newptr->next=predptr->next;
predptr->next=newptr;
break;
}
//循環
predptr=predptr->next;
}
}
//遍歷一下
traverse();
}
//find
void
find(void)
{
printf("輸入要查找的數字:");
int n=getint();
node *ptr=first;
while(ptr!=NULL)
{
if(ptr->n==n)
{
printf("\n已找到%d\n",n);
usleep(100000);
break;
}
ptr=ptr->next;
}
if(ptr==NULL)
printf("你所要尋找的數字不存在\n");
}
//traverse
void
traverse(void)
{
printf("現在列表中存在的數據有:");
node *ptr=first;
while(ptr!=NULL)
{
printf("%d ",ptr->n);
ptr=ptr->next;
}
fflush(stdout);
usleep(100000);
printf("\n\n");
}