單鏈表
1.概念
為了表示每個數據元素a(i)
與它下一個元素a(i+1)
之間的邏輯關系,對數據元素a(i)
來說除了儲存儲本身的信息之外,還需存儲一個表示它下一個元素的信息。這兩部分信息組成數據元素a(i)
的存儲映像,稱為節點
,它包括兩個域:存本身信息的叫數據域
,存直接后繼位置的叫指針域
。n個節點鏈接成一個鏈表
,即為線性表(a1,a2,a3.....an)的鏈式存儲結構
。由於每個節點中只存在一個指針域所以我們稱之為單鏈表
或線性鏈表。
2.特點
1)順序存取
2)儲存數據元素的儲存單元可連續可不連續。
3.補充
根據鏈表節點所含指針個數、指針指向和指針鏈接方式,可將鏈表分為單鏈表
、循環鏈表、雙向鏈表、二叉鏈表
、十字鏈表
、鄰接表
、鄰接多重表
等。其中單鏈表、循環鏈表、和雙向鏈表用於實現線性表的鏈式
存儲結構,其他形式多用於實現樹
和圖
等非線性結構。
實例
4.單鏈表的存儲結構
typtypedef struct
{
char no[20];
char name[20];
float price;
}Book;
typedef struct LNode
{
Book data; //數據域
struct LNode *next; //指針域
}LNode,*LinkList; //LinkList為指向結構體LNode的指針類型
注:
1)LNode *
和LinkList
等價。
2)LNode *
強調定義鏈表中的某個節點,如LNode *p
p代表指向某個節點的指針。
3)LinkList
強調定義鏈表指向頭結點的頭指針,如LinkList L
L代表頭指針簡稱表L。
5.幾個概念區分
首元結點
:指向鏈表中存儲第一個數據元素a1的節點。
頭結點
:為處理方便在單鏈表第一個節點之前附設的一個節點,他的數據域可以為空。
頭指針
:指向鏈表中第一個節點的指針。有頭結點則指向頭結點,無頭結點則指向首元結點。
實例
6-1.簡單鏈表
#include <iostream>
#include <string.h>
#define OK 1
#define ERROR 0
using namespace std;
typedef struct node{
int data;
struct node*next;
}node,*Lnode;
void init(Lnode &L)
{
L=new node;
L->next = NULL;
}
void add(Lnode &L,Lnode &R,int d)
{
node *n=new node;
n->data=d;
n->next=NULL;
R->next=n;
R=n;
}
void display(Lnode L)
{
node *p=NULL;
p=L->next;
while(p)
{
cout<<"==>"<<p->data;
p=p->next;
}
}
void newlist(Lnode &L,Lnode &R)
{
int n=1;
while(n)
{
int t;
cout<<"InPut.";cin>>t;
add(L,R,t);
cout<<" Do you want new a node[1/0] agin?"<<endl;
cin>>n;
}
}
int main()
{
Lnode L,R;
init(L);
R=L;
newlist(L,R);
display(L);
}
6-2.簡單圖書管理系統
#include <iostream>
#include <string.h>
#define OK 1
#define ERROR 0
using namespace std;
//數據元素
typedef struct
{
char no[20];
char name[20];
float price;
}Book;
//節點
typedef struct LNode
{
Book data; //數據域
struct LNode *next; //指針域
}LNode,*LinkList; //LinkList為指向結構體LNode的指針類型
//單鏈表初始化
int InitList(LinkList &L)
{
L = new LNode; //L指向新生成的頭結點
L->next = NULL; //頭結點指針域置空
return OK;
}
//取值
int GetBook(LinkList L,int i,Book &b)
{
LNode *p;
p=L->next;int j=1; //p指向首元結點,j計數器
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i)//該節點不存在或i值不合法
{
return ERROR;
}
b=p->data;
return OK;
}
void out_book(Book b);
//查找
LNode *LocateBook(LinkList L,Book b)
{
LNode *p;
p = L->next; //p指向首元結點
while(p&&strcmp(p->data.no,b.no)!=0) //當p不為空且p的數據域不等於b
{
p=p->next; //指向下一個節點
}
return p; //p為b的地址,查找失敗p為NULL
}
//插入
int ListInsert(LinkList &L,int i,Book b)
{
LNode *p;
p=L;int j=0;
while(p&&(j<i-1))//找到插入位置i的前一個節點
{
p=p->next;
++j;
}
if(!p||j>i-1) //i>L.length,或i<1
{
return ERROR;
}
LNode *s=NULL; //構造新節點s
s->data = b;
s->next = p->next;
p->next = s;
return OK;
}
//刪除
int ListDelete(LinkList &L,int i)
{
LNode *p;
p=L;int j=0;
while((p->next)&&(j<i-1)) //插入有n+1個合法位置刪除只有n個,防止引用空指針
{ //使用p->next作為判斷條件
p=p->next;
++j;
}
if(!(p->next)||(j>i-1))
{
return ERROR;
}
LNode *t;
t = p->next;
p->next = t->next;
delete t;
return OK;
}
//添加節點(后插法)
int AddNode(LinkList &L,LinkList &R,Book b)
{
LNode *n= new LNode; //相當於LNode *n;LNode k;n=&k;
n->data=b;n->next=NULL;
R->next=n; //把新建節點連到尾結點
R=n; //尾指針指向新建節點
return OK;
}
void in_book(Book &t)
{
cout<<"\nISBN:";cin>>t.no;cout<<"書名:";cin>>t.name;cout<<"價格:";cin>>t.price;
}
void out_book(Book b)
{
cout<<"ISBN "<<b.no<<" |書名 "<<b.name<<" |價格 "
<<b.price<<endl;
return;
}
void display(LinkList L)
{
LNode *p=NULL;
p=L->next;
while(p)
{
out_book(p->data);
p=p->next;
}
return;
}
//創建單鏈表(后插法)
void CreateList(LinkList &L,LinkList &R)
{
int n=1;
while(n)
{
Book t;
cout<<"\t[數據錄入]"<<endl;
in_book(t);
AddNode(L,R,t);
cout<<"\t是[1]否[0]繼續?"<<endl;
cin>>n;
}
}
//刪
void del_book(LinkList &L)
{
int i;
cout<<"\t[刪除數據]\n序號:"<<endl;
cin>>i;
ListDelete(L,i);
return;
}
//查
void search_book(LinkList &L)
{
cout<<"\t[查找數據]\nISBN:"<<endl;
Book b;
cin>>b.no;
LNode *p=LocateBook(L,b);
out_book(p->data);
return;
}
//改
void edi_book(LinkList &L)
{
Book b,t;
cout<<"\t[修改數據]\nISBN:"<<endl;
cin>>b.no;
LNode *p=LocateBook(L,b);
in_book(t);
p->data = t;
return;
}
void get_book(LinkList &L)
{
int i;Book g;
cout<<"\t[獲取數據]\n序號:"<<endl;
cin>>i;
GetBook(L,i,g);
out_book(g);
return;
}
int main()
{
//初始化得到空單鏈表L
LinkList L,R;
InitList(L);
R=L; //尾指針R暫指到頭結點
//增
CreateList(L,R);
display(L);
//刪
del_book(L);
display(L);
//查
search_book(L);
//改
edi_book(L);
display(L);
//取
get_book(L);
return 0;
}
7-1.運行結果
7-2.運行結果
增
刪
查
改
取
此處按序號取第5個數據,即ISBN為6的數據
8.附:前插法
//創建單鏈表(前插法)
int CreateList(LinkList &L,Book b)
{
LNode *n=new LNode;
n->data=b;
n->next=L->next;//新建節點插入到頭結點之后(即首元結點之前)
L->next=n;
}