链表

1、链表思想:每个节点都存储分为数据和地址两个方面。

数据是链表记录的内容,地址分为此节点的地址和它的前驱和后缀地址。

通过,每次通过地址来时先链表的遍历,查找,删除等操作。

2、链表分类

如果是单链表,就是只有后继,只能向后移动,因此,为了方便查找链表的某个节点,常常设置头结点。

双向链表:同时具有前驱和后缀,可以向前或者向后移动。

循环链表:最后的单元反过来,直至第一个单元,可以有表头,也可以是双向链表

3、链表的具体实现操作:

(1)单链表的实现

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>

#define ERRROR -1

//链表的结构 
typedef int ElementType;
struct Node{
    ElementType x;
    struct Node *next;
};
typedef struct Node* List;
typedef List Position;

//链表的操作
List MakeEmpty(List L);
int IsEmpty(List L);
int IsLast(Position p,List L);
Position Find(ElementType x,List L);
void Delete(ElementType x,List L);
Position FindPrevious(ElementType x,List L);
void Insert(ElementType x,List L,Position p);
void DeleteList(List L);


//测试是否为空表
int IsEmpty(List L)
{
    return L->next==NULL;
}

//测试是否为最后一个节点 
int IsLast(Position p,List L)
{
    return p->next==NULL;
}

//初始化
List Init(List L)
{
    L = (List)malloc(sizeof(struct Node));
    if(L==NULL)
    {
        printf("Out of Space!
");
    }
    else L->next=NULL;
    return L;
}
 
//查找函数 
Position Find(ElementType x,List L)
{
    List p=L;
    while(p!=NULL&&p->x!=x)
    {
        p=p->next;
    }
    return p;
} 

//删除链表 
void Delete(ElementType x,List L)
{
    List tp,p;
    p=FindPrevious(x,L);
    if(!IsLast(p,L))
    {
        tp=p->next;
        p->next=tp->next;
        free(tp);
    }
}

//查找前一个元素 
Position FindPrevious(ElementType x,List L)
{
    Position p=L;
    while(p->next!=NULL&&p->next->x!=x)
    {
        p=p->next;
    }
    return p;
}

//插入
void Insert(ElementType x,List L,Position p)
{
    List tp;
    tp=(List)malloc(sizeof(struct Node));
    if(tp==NULL)
    {
        printf("Out of Space!!!
");
    }
    tp->x=x;
    tp->next=p->next;
    p->next=tp; 
} 

//删除
void DeleteList(List L)
{
    List p,tp;
    tp=L->next;
    L->next=NULL;
    while(tp!=NULL)
    {
        p=tp->next;
        free(tp);
        tp=p;
    }
}

void Print(List L)
{
    List p=L->next;
    while(p!=NULL)
    {
        printf("%d ",p->x);
        p=p->next;
    }
    printf("
");
}

int main(void)
{
    List L,p;
    L=Init(L);
    p=L;
    int i,x,n;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        Insert(x,L,p);
        p=p->next;
    }
    Print(L);
    
    printf("将7插入3的前面:
");
    p=FindPrevious(3,L);
    Insert(7,L,p);
    Print(L);
    
    printf("删除4:
");
    Delete(4,L);
    Print(L);
    
    return 0;
}
View Code

(2)双向链表

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct Node{
    int data;
    struct Node *Pre,*Rear;
};
typedef struct Node* DoList;

DoList Init(DoList L) //初始化 
{
    L=(DoList)malloc(sizeof(struct Node));
    L->Pre=NULL;
    L->Rear=NULL;
    return L;
}

int IsEmpty(DoList L) //判断是否为空 
{
    if(L->Pre==NULL&&L->Rear==NULL) return 1;
    return 0;
}

int IsLast(DoList L,DoList p) //判断最后一个元素 
{
    if(p->Pre!=NULL&&p->Rear==NULL) return 1;
    return 0;
}

DoList FindPrevious(int x,DoList L) //找到前一个元素 
{
    DoList p=L;
    while(p->Rear!=NULL&&p->Rear->data!=x)
    {
        p=p->Rear;
    }
    return p;
}

void Insert(int x,DoList L,DoList p) //插入某个元素 
{
    DoList tp=(DoList)malloc(sizeof(struct Node));
    if(tp==NULL)
    {
        printf("Out of Space!!!
");
    }
    //printf("%d
",x);
    tp->data=x;
    //先前再后
    tp->Pre=p;
    tp->Rear=p->Rear;  
    if(p->Rear==NULL) p->Rear=tp; //这里要注意,因为可能存在p->Rear==NULL的情况。 
    else
    {
        p->Rear->Pre=tp;
        p->Rear=tp;
    }
}

void Delete(int x,DoList L) //删除某个元素 
{
    DoList p,tp;
    p=FindPrevious(x,L);
    tp=p->Rear;
    p->Rear=tp->Rear;
    tp->Rear->Pre=p;
    free(tp);
}

void Print(DoList L) //正序输出 
{
    DoList p=L->Rear;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->Rear;
    }
    printf("
");
}

void RePrint(DoList L) //逆序输出
{
    DoList p,tp;
    p=L->Rear;
    while(!IsLast(L,p)) p=p->Rear;
    while(p->Pre!=NULL)
    {
        printf("%d ",p->data);
        p=p->Pre;
    }
    printf("
");
}

void DeleteList(DoList L) //输出链表 
{
    DoList p,tp;
    p=L->Rear;
    L->Rear=NULL;
    while(p!=NULL)
    {
        tp=p->Rear;
        free(p);
        p=tp;
    }
}

int main(void)
{
    DoList L,p;
    L=Init(L);
    p=L;
    int n,x,i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        Insert(x,L,p);
        p=p->Rear;
    }
    Print(L);
    
    p=FindPrevious(3,L);
    Insert(7,L,p);
    //DeleteList(L); 
    RePrint(L);
    return 0;
}
View Code

(3)循环链表

循环单链表

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct Node{
    int data;
    struct Node *next;
}; 
typedef struct Node* CyList;

CyList Init(CyList L)
{
    L=(CyList)malloc(sizeof(struct Node));
    L->data=-1;
    L->next=L;
    return L;
}

int Empty(CyList L)
{
    return L->next==L;
}

CyList FindPrevious(int x,CyList L)
{
    CyList p=L;
    while(p->next->data!=x&&p->next!=NULL)
    {
        p=p->next;
    }
    return p;
}

void Insert(int x,CyList L,CyList p)
{
    CyList tp=(CyList)malloc(sizeof(struct Node));
    tp->data=x;
    tp->next=p->next;
    p->next=tp;
}

void Delete(int x,CyList L)
{
    CyList p,tp;
    p=FindPrevious(x,L);
    if(p->next!=NULL)
    {
        tp=p->next;
        p->next=tp->next;
        delete tp;
    }
}

void Print(CyList L)
{
    CyList p=L->next;
    while(p!=L)
    {
        printf("%d ",p->data);
        p=p->next;
    } 
    printf("
");
}

void DeleteList(CyList L)
{
    CyList p,tp;
    p=L->next;
    L->next=L;
    while(p!=L)
    {
        tp=p->next;
        delete p;
        p=tp;
    }
}

void DoPrint(CyList L)
{
    CyList p=L->next;
    int tim=0;
    while(1)
    {
        if(tim==1&&p==L) break;
        if(p==L&&tim==0)
        {
            p=p->next;
            tim=1;continue;
        }
        printf("%d ",p->data);
        p=p->next;
    }
}

int main(void)
{
    CyList L,p;
    L=Init(L);
    p=L;
    int n,i,x;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        Insert(x,L,p);
        p=p->next;
    }
    p->next=L;
    Print(L);
    
    p=FindPrevious(3,L);
    Insert(7,L,p);
    Print(L);
    
    Delete(2,L);
    Print(L);
    
    DoPrint(L);
    return 0;
}
View Code

循环双向链表

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct Node{
    int data;
    struct Node *Pre,*Rear;
};
typedef struct Node* DuList;

DuList Init(DuList L)
{
    L=(DuList)malloc(sizeof(struct Node));
    L->Pre=L;
    L->Rear=L;
    return L;
}

int IsEmpty(DuList L)
{
    if(L->Pre==L&&L->Rear==L) return true;
    return false;
}

void Insert(int x,DuList L,DuList p)
{
    DuList tp=(DuList)malloc(sizeof(struct Node));
    tp->data=x;
    tp->Pre=p;
    tp->Rear=p->Rear;
    p->Rear->Pre=tp;
    p->Rear=tp;
}

DuList FindPrevious(int x,DuList L)
{
    DuList p=L;
    while(p->data!=x) p=p->Rear;
    return p->Pre;
}

void Delete(int x,DuList L)
{
    DuList p,tp;
    p=FindPrevious(x,L);
    tp=p->Rear;
    p->Rear=tp->Rear;
    tp->Rear->Pre=p;
}

void Print(DuList L)
{
    DuList p=L;
    printf("%d ",p->data);
    p=p->Rear;
    while(p!=L)
    {
        printf("%d ",p->data);
        p=p->Rear;
    }
    printf("
");
}

void DeleteList(DuList L)
{
    DuList p=L->Rear,tp=L;
    delete tp;
    L=NULL;
    while(p!=NULL)
    {
        tp=p->Rear;
        delete tp;
        p=tp;
    }
}

int main(void)
{
    int n,x,i;
    DuList p,L;
    scanf("%d",&n);
    scanf("%d",&x);
    p=Init(p);
    p->data=x;
    L=p;
    for(i=1;i<n;i++)
    {
        scanf("%d",&x);
        Insert(x,L,p);
        p=p->Rear;
    }
    Print(L);
    
    Delete(3,L);
    Print(L);
    
    p=FindPrevious(2,L);
    Insert(7,L,p);
    Print(L);
    
    return 0; 
}
View Code

注意:1、如果对p->next进行操作,p一定不能为空,否则会出问题。

2、双向链表中的插入操作,先对tp的前驱操作,再对tp的后驱操作。

3、循环链表的最大特征就是首尾相连,空表时,自己指向自己(指的是单链表的头结点,如果是双向链表,直接让第一个节点的前驱指向最后一个节点,

最后一个节点的后驱指向第一个节点就行了)。

书后练习:

3.2:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>

struct Node{
    int id,data;
    struct Node* next;
};
typedef struct Node* List;

List Init(List L)
{
    L=(List)malloc(sizeof(struct Node));
    L->next=NULL;
    return L;
}

void Insert(int x,List L,List p)
{
    List tp=(List)malloc(sizeof(struct Node));
    tp->data=x;
    if(tp==NULL)
    {
        printf("Out of Space!!!
");
    }
    tp->next=p->next;
    p->next=tp;
}

int FindNum(List L,int pos)
{
    List tp,p=L->next;
    int i=1;
    while(p!=NULL&&i!=pos)
    {
        i++;p=p->next;
    }
    return p->data;
}

void PrintLots(List L,List p)
{
    List tp=p->next;
    while(tp!=NULL)
    {
        printf("%d ",FindNum(L,tp->data));
        tp=tp->next;
    }
    printf("
");
}

void Print(List L)
{
    List p=L->next;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    printf("
");
}

int main(void)
{
    int begintime=0,endtime;
    List L1,p,L2;
    L1=Init(L1);
    L2=Init(L2);
    p=L1;
    int n,x,i;
    printf("创建L序列:
");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        Insert(x,L1,p);
        p=p->next;
    }
    Print(L1);
    
    printf("创建P序列:
");
    p=L2;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        Insert(x,L2,p);
        p=p->next;
    }
    Print(L2);
    
    PrintLots(L1,L2);
    endtime=clock();
    printf("程序运行时间为:%dmm
",endtime-begintime);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/2018zxy/p/10017542.html