鏈表(一)單鏈表


單鏈表
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 *pp代表指向某個節點的指針。
3)LinkList強調定義鏈表指向頭結點的頭指針,如LinkList LL代表頭指針簡稱表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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM