链表(陈锐、葛丽萍编著《跟我学数据结构》整理

  链表通过自引用结构体类型的指针成员指向结构体本身建立起来,“自引用结构体”包含一个指针成员,该指针指向与结构体一样的类型。

struct node 
{
    int data;//整形成员
    struct node *next;//指针成员
};

自引用结构体单元称为节点,jie'结点之间通过箭头连接qi'l起来,构成一个表,成为链表。

链表中zhi'指向第一个节点的指针chen成为头指针,tong通过头指针,可以访问链表的每一个结点。

链表的最后一个节点的指针部分用空(NULL)表示。

为了方便,在链表的第一个结点之前增加一个结点,称为tou'头结点。

不带头节点的指针   head ->[a   ]->[b   ]->[c   ]->[d  ^]      

带头节点de'z的指针 head->[      ]->[a    ]->[b    ]->[c   ]->[d   ^]

单链表的存储结构

typedef struct Node
{
    DataType data;
    struct Node *next;
} ListNode,*LinkList;

其中,ListNode是lian链表的结点类型,LinkList 是指向链表节点的指针类型

定义LinkList L;定义了一个链表,L指向该链表的第一个结点,对于不带头结点的链表来说,如果链表为空,则有L=NULL;

对于带头结点的链表,如果链表为空,则L->next=NULL;

单链表上的基本运算

1.单链表的初始化

void InitList(LinkList *head)
//将单链表初始化为空,动态生成一个头节点,并将头结点的指针域置为空。
{
   if((*head=(LinkList)malloc(sizeof(ListNode)))==NULL)//为头节点分配一个存储空间。
        exit(-1);
   (*head)->next=NULL;//将单链表的头结点的指针域置为空
}

2.判断单链表是否为空,

int ListEmpty(LinkList head)
//判断单链表是否为空,通过判断头结点的指针域是否为空
{
    if(head->next==NULL)//判断单链表头结点的指针域是否为空。
        return 1;
    else
        return 0;
}

3.按序号查找操作

///按序号查找操作;从头指针head出发,利用节点的next 域,扫描链表的结点。
ListNode* Get(LinkList head,int i)
{
    ListNode *p;
    int j;
    if(ListEmpty(head)) return NULL;
    if(i<1) return NULL;
    j=0;
    p=head;
    while(p->next!=NULL&&j<i)
    {
        p=p->next;
        j++;
    }
    if(j==i)  return  p;
    else return NULL;
}

4.///按内容查找操作

///按内容查找操作
ListNode* LocateElem(LinkList head,DataType e)
{
    ListNode *p;
    p=head->next;
    while(p)
    {
        if(p->data !=e)
            p=p->next;
        else
            break;
    }
    return p;
}

5。定位操作

int LocatePos(LinkList head,DataType e)
{
    ListNode *p;
    int i;
    if(ListEmpty(head))  return 0;
    p=head->next;///p指向第一个节点
    i=1;
    while(p)
    {
        if(p->data==e)  return i;
        else
        {
            p=p->next;
            i++;
        }
    }
    if(!p) ///没有找到与e相等的元素,表示失败,返回0;
    return 0;
}

6.cha'插入操作

///插入操作,在单链表的第i个位置插入一个节点,节点元素的值为e,插入成功返回1,插入失败返回0;
int InsertList(LinkList head,int i,DataType e)
{
    ListNode *p,*pre;
    ///定义指向第i个元素的前驱结点指针pre,指针p指向新生成的结点
    int j;
    pre=head;
    j=0;
    while(pre->next!=NULL&&j<i-1)
    {
        pre=pre->next;
        j++;
    }
    if(j!=i-1)
    {
        printf("插入位置错误");
        return 0;
    }
    //x新生成一个结点,并将 E赋值给该i节点的数据域
    if((p=(ListNode*)malloc(sizeof(ListNode)))==NULL)
        exit(-1);
        ///插入节点操作;
    p->data=e;
    p->next=pre->next;
    pre->next=p;
    return 1;
}

7.删除操作

int DeleteList(LinkList head,int i,DataType *e)
{
    ListNode *pre,*p;
    int j;
    pre=head;
    j=0;
    while(pre->next!=NULL&&pre->next->next!=NULL && j<i-1)
    {
        pre=pre->next;
        j++;
    }
    if(j!=i-1)
    {
        printf("删除位置错误");
        return 0;
    }
    ///删除操作
    ///指针p指向单链表中的第i个结点,并将该节点的数据域值赋值给E
    p=pre->next;
    *e=p->data;
    pre->next=p->next;
    free(p);
    return 1;
}

8.求表长

///求表长操作
int ListLength(LinkList head)
{
    ListNode *p;
    int count = 0;
    p=head;
    while(p->next!=NULL)
    {
        p=p->next;
        count++;
    }
    return count;
}

9.销毁链表

///销毁链表操作
void DestroyList (LinkList head)
{
    ListNode *p,*q;
    p=head;
    while(p!=NULL)
    {
        q=p;
        p=p->next;
        free(q);
    }
}

应用举例:单链表应用举例:实现如果单链表A中出现的元素在单链表B中也出现,则将A中该元素删除。

///l单链表应用举例:
#include <iostream>
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef int DataType;
typedef struct Node
{
    DataType data;
    struct Node *next;
} ListNode,*LinkList;
//单链表上的基本运算
void InitList(LinkList *head)
//将单链表初始化为空,动态生成一个头节点,并将头结点的指针域置为空。
{
   if((*head=(LinkList)malloc(sizeof(ListNode)))==NULL)//为头节点分配一个存储空间。
        exit(-1);
   (*head)->next=NULL;//将单链表的头结点的指针域置为空
}
int ListEmpty(LinkList head)
//判断单链表是否为空,通过判断头结点的指针域是否为空
{
    if(head->next==NULL)//判断单链表头结点的指针域是否为空。
        return 1;
    else
        return 0;
}
///按序号查找操作;从头指针head出发,利用节点的next 域,扫描链表的结点。
ListNode* Get(LinkList head,int i)
{
    ListNode *p;
    int j;
    if(ListEmpty(head)) return NULL;
    if(i<1) return NULL;
    j=0;
    p=head;
    while(p->next!=NULL&&j<i)
    {
        p=p->next;
        j++;
    }
    if(j==i)  return  p;
    else return NULL;
}
///按内容查找操作
ListNode* LocateElem(LinkList head,DataType e)
{
    ListNode *p;
    p=head->next;
    while(p)
    {
        if(p->data !=e)
            p=p->next;
        else
            break;
    }
    return p;
}
int LocatePos(LinkList head,DataType e)
{
    ListNode *p;
    int i;
    if(ListEmpty(head))  return 0;
    p=head->next;///p指向第一个节点
    i=1;
    while(p)
    {
        if(p->data==e)  return i;
        else
        {
            p=p->next;
            i++;
        }
    }
    if(!p) ///没有找到与e相等的元素,表示失败,返回0;
    return 0;
}
///插入操作,在单链表的第i个位置插入一个节点,节点元素的值为e,插入成功返回1,插入失败返回0;
int InsertList(LinkList head,int i,DataType e)
{
    ListNode *p,*pre;
    ///定义指向第i个元素的前驱结点指针pre,指针p指向新生成的结点
    int j;
    pre=head;
    j=0;
    while(pre->next!=NULL&&j<i-1)
    {
        pre=pre->next;
        j++;
    }
    if(j!=i-1)
    {
        printf("插入位置错误");
        return 0;
    }
    //x新生成一个结点,并将 E赋值给该i节点的数据域
    if((p=(ListNode*)malloc(sizeof(ListNode)))==NULL)
        exit(-1);
        ///插入节点操作;
    p->data=e;
    p->next=pre->next;
    pre->next=p;
    return 1;
}
int DeleteList(LinkList head,int i,DataType *e)
{
    ListNode *pre,*p;
    int j;
    pre=head;
    j=0;
    while(pre->next!=NULL&&pre->next->next!=NULL && j<i-1)
    {
        pre=pre->next;
        j++;
    }
    if(j!=i-1)
    {
        printf("删除位置错误");
        return 0;
    }
    ///删除操作
    ///指针p指向单链表中的第i个结点,并将该节点的数据域值赋值给E
    p=pre->next;
    *e=p->data;
    pre->next=p->next;
    free(p);
    return 1;
}

///求表长操作
int ListLength(LinkList head)
{
    ListNode *p;
    int count = 0;
    p=head;
    while(p->next!=NULL)
    {
        p=p->next;
        count++;
    }
    return count;
}
///销毁链表操作
void DestroyList (LinkList head)
{
    ListNode *p,*q;
    p=head;
    while(p!=NULL)
    {
        q=p;
        p=p->next;
        free(q);
    }
}
void DelElem(LinkList *A ,LinkList B)//解决问题的函数
{
    int i,pos;
    DataType e;
    ListNode *p;
    for(i=1;i<=ListLength(B);i++)
    {
        p=Get(B,i);
        if(p)
        {
           pos=LocatePos(*A,p->data);
           if(pos>0) DeleteList(*A,pos,&e);
        }
    }
}
using namespace std;

int main()
{
    int i;
    DataType a[]={6,7,9,14,37,45,65,67};
    DataType b[]={3,7,11,34,45,89};
    LinkList A,B,C;
    ListNode *p;
    InitList(&A);
    InitList(&B);
    InitList(&C);
    for(i=1;i<=sizeof(a)/sizeof(a[0]);i++)
    {
        if(InsertList(A,i,a[i-1])==0)
        {
            printf("位置不合法");
            return 0 ;
        }
    }
    for(i=1;i<=sizeof(b)/sizeof(b[0]);i++)
    {
        if(InsertList(B,i,b[i-1])==0)
        {
            printf("位置不合法");
            return 0;
        }
    }
    printf("A中的元素有%d个\n",ListLength(A));
    for(i=1;i<=ListLength(A);i++)
    {
        p=Get(A,i);
        if(p)
            printf("%4d",p->data);
    }
    printf("\n");
    printf("单链表B中的元素有 %d个:\n",ListLength(B));
    for(i=1;i<=ListLength(B);i++)
    {
        p=Get(B,i);
        if(p)
            printf("%4d",p->data);
    }
    printf("\n");
    DelElem(&A,B);
    printf("将在A中出现B的元素删除后,现在A 中的元素还有%d个:\n",ListLength(A));
    for(i=1;i<=ListLength(A);i++)
    {
        p=Get(A,i);
        if(p)
            printf("%4d",p->data);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41929516/article/details/84935569
今日推荐