帶頭結點的連結串列實現通訊錄
阿新 • • 發佈:2018-12-31
關於連結串列使用二級指標或者一級指標引用的問題:
1、使用二級指標完全可以代替一級指標。在沒有頭結點的情況下必須使用二級指標,使用一級指標無效。
2、而如果不用二級指標,直接傳一個一級指標,相當於生成L的拷貝M,但是對M分配空間與L無關了。
3、只要是修改頭指標則必須傳遞頭指標的地址,否則傳遞頭指標值即可(即頭指標本身)。這與普通變數類似,當需要修改普通變數的值,需傳遞其地址,否則傳遞普通變數的值即可(即這個變數的拷貝)。使用二級指標,很方便就修改了傳入的結點一級指標的值。 如果用一級指標,則只能通過指標修改指標所指內容,卻無法修改指標的值,也就是指標所指的記憶體塊。所以建立連結串列和銷燬連結串列需要二級指標或者一級指標引用。
4、不需要修改頭指標的地方用一級指標就可以了,比如插入,刪除,遍歷,清空結點。假如頭指標是L,則對L->next 及之後的結點指標只需要傳遞一級指標。
5、比如一個結點p,在函式裡要修改p的指向就要用二級指標,如果只是修改p的next指向則用一級指標就可以了
函式中傳遞指標,在函式中改變指標的值,就是在改變實參中的資料資訊。但是這裡改變指標的值實際是指改變指標指向地址的值,因為傳遞指標就是把指標指向變數的地址傳遞過來,而不是像值傳遞一樣只是傳進來一個實參副本。所以當我們改變指標的值時,實參也改變了。
headlist.h:
#ifndef _HEADLIST_H #define _HEADLIST_H #define OK 0 #define ERROR -1 typedef struct _node { char name[10]; int data; struct _node *next; }Node; //建立連結串列 Node *createList(); // 尾法插入元素 int insertLast(Node *head); //輸出通訊錄內容 void display(Node *head); //在指定位置插入元素 int insertPos(Node *head,int pos); //根據姓名刪除元素 int deleteData(Node *head,char *name); //根據姓名修改元素ID int modifyData(Node *head,char *name); //根據id查詢元素 int LocateElem(Node *head,int data); //逆序 int ReverseLinkList(Node *head); #endif
headlist.c:
#include"headlist.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//建立連結串列就是建立一個頭結點
Node *createList()
{
Node * pNode=(Node*)malloc(sizeof(Node)/sizeof(char));
if(pNode==NULL)
{
printf("Failed to create header\n");
return NULL; //返回值型別為指標,所以用NULL
}
pNode->next=NULL;
return pNode;
}
//逆序
int ReverseLinkList(Node *head)
{
if(head==NULL)
return ERROR;
Node *tmp1=head->next;
head->next=NULL;
while(tmp1)
{
Node *tmp2=tmp1;
tmp1=tmp1->next;
tmp2->next=head->next;
head->next=tmp2;
}
return OK;
}
//根據id查詢元素
int LocateElem(Node *head,int data)
{
if(head==NULL)
return ERROR;
Node *tmp=head;
while(tmp)
{
if(tmp->data==data)
{
printf("找到的元素資訊為:\n");
printf("%s\n",tmp->name);
printf("%d\n",tmp->data);
break;
}
tmp=tmp->next;
}
return OK;
}
//根據姓名修改元素ID
int modifyData(Node *head,char *name)
{
if(head==NULL)
return ERROR;
Node *tmp=head;
while(tmp)
{
if(strcmp(tmp->name,name)==0)
{
int data;
printf("請輸入元素修改後的ID:\n");
scanf("%d",&data);
tmp->data=data;
return OK;
}
tmp=tmp->next;
}
return ERROR;
}
//根據姓名刪除元素
int deleteData(Node *head,char *name)
{
if(head==NULL)
return ERROR;
Node *tmp=head;
while(tmp->next) //為了跨結點連線
{
if(strcmp(tmp->next->name,name)==0)
{
//tmp->next=tmp->next->next;
//free(tmp->next);
Node *p=tmp->next; /* 為什麼要 p */
tmp->next=p->next;
free(p);
return OK; //正確刪除,返回ok
}
tmp=tmp->next;
}
return ERROR;
}
//根據位置插入元素
int insertPos(Node *head,int pos)
{
if (head == NULL)
return ERROR;
//遍歷到元素的位置,準備插入
int i;
Node *tmp=head;
for(i=0;i<pos-1;i++)
{
if(tmp==NULL)
{
printf("沒有pos 這個位置\n");
return ERROR;
}
tmp=tmp->next;
} //tmp遍歷到pos-1處
//為新結點建立空間並賦值
Node *node=(Node*)malloc(sizeof(Node)/sizeof(char));
if(node==NULL) //此處 起初將Node 寫成node ,malloc 沒有成功,報錯 "invalid next size (fast):"
return ERROR;
int data;
char name[10];
printf("請輸入插入使用者的姓名:\n");
scanf("%s",name);
printf("請輸入插入使用者的ID:\n");
scanf("%d",&data);
strcpy(node->name,name);
node->data=data;
//新結點的指標域指向 tmp 的後繼,tmp 指向新結點node,完成插入
node->next=tmp->next;
tmp->next=node;
return OK;
}
// 尾法插入資料
int insertLast(Node *head)
{
if (head == NULL)
return ERROR;
//為新插入的結點建立空間並賦值
Node * node = (Node*)malloc(sizeof(Node)/sizeof(char));
if (node == NULL)
return ERROR;
int data;
char name[10];
printf("請輸入好友姓名\n");
scanf("%s",name);
printf("請輸入好友ID\n");
scanf("%d",&data);
strcpy(node->name,name); //新結點的賦值
node->data = data;
node->next = NULL;
// 找最後一個結點,準備插入
Node *tmp = head;
while (tmp->next)
{
tmp = tmp->next;
}
//將尾結點的指標域指向新結點,完成尾插
tmp->next = node;
return OK;
}
void display(Node *head)
{
if (head == NULL)
return; //void 型別函式返回值寫法
// 第一個結點
Node *tmp = head->next;
while (tmp)
{
printf("%s\n",tmp->name);
printf ("%d\n", tmp->data);
tmp = tmp->next; // 下一個元素
}
printf ("\n");
}
main.c
#include<stdio.h>
#include<stdlib.h>
#include "headList.h"
int main()
{
printf("歡迎來到蘇嵌教育\n");
Node *pNode=createList();
if(pNode==NULL)
return ERROR;
int i,pos,a,data;
char name[10];
for(i=0;i<3;i++)
{
insertLast(pNode); //如果用二級指標,這裡的實參要改為 &pNode, .c 和 .h 檔案中的函式形參要改為
} //Node **head, 函式中 head 要改為 (*head)
printf("尾插法後的通訊錄為:\n");
display(pNode);
while(1)
{
printf("請選擇以下功能;\n");
printf("1.插入好友資訊\n");
printf("2.刪除好友資訊\n");
printf("3.修改好友資訊\n");
printf("4.查詢好友\n");
printf("5.通訊錄逆序檢視\n");
printf("6.退出\n");
scanf("%d",&a);
if(a>6)
printf("無此功能\n");
switch(a)
{
case 1:
printf("請輸入要插入的位置:\n");
scanf("%d",&pos);
insertPos(pNode,pos);
printf("插入新元素後的通訊錄為:\n");
display(pNode);
break;
case 2:
printf("請輸入要刪除元素的姓名:\n");
scanf("%s",name);
deleteData(pNode,name);
printf("刪除元素後的通訊錄為:\n");
display(pNode);
break;
case 3:
printf("請輸入要修改元素的姓名:\n");
scanf("%s",name);
modifyData(pNode,name);
printf("修改後的通訊錄為:\n");
display(pNode);
break;
case 4:
printf("請輸入要查詢元素的id:\n");
scanf("%d",&data);
LocateElem(pNode,data);
break;
case 5:
ReverseLinkList(pNode);
printf("逆序後的通訊錄為:\n");
display(pNode);
break;
case 6:
exit(0);
break;
}
}
return OK;
}