数据结构复习----线性表

目录

一.线性表的基本操作

1.&表示C++语言中的引用调用

(1)未使用&时的代码

(2)使用&时的代码:

二、顺序表的基本操作

 1.顺序表的静态分配

(1)不进行初始化,会发生内存中会有遗留的“脏数据”

 (2)进行初始化

2.顺序表的动态分配

(1)key:动态申请和释放内存空间:

(2)代码实现:

​编辑  3.顺序表的插入

(1)代码

4.线性表的删除

(1)代码

5.线性表的按位查找

 ​编辑

6.线性表的按值查找

三、单链表的基本操作

1、用代码定义一个单链表

(1)定义单链表

(2)不带头结点的单链表

(3)带头结点的单链表

2.按位序插入

(1)带头结点按位序插入

 (2)不带头结点按位序插入

3.指定结点的插入操作

(1)指定结点的后插操作

 (2)带头结点的指定位置的后插操作

 (3)不带头节点的指定位置后插操作

 (4)带头结点指定节点的前插操作

 (5)不带头节点的前插操作

 (6)指定结点的前插操作(采用交换覆盖的方法)

4.按位序删除

(1)带头结点的按位序删除

(2)不带头结点按位序删除

 (3)指定节点的删除

5.封装综合

按位查找或者按值查找并进行封装删除,后插,前插,求表长操作

 6.尾插法建立单链表

(1)带头结点尾插法

(2)不带头节点的尾插法

 7.头插法建立单链表

(1)带头结点头插法

 (2)不带头结点头插法

 8.循环单链表

封装综合

四、双链表的基本操作

1.双链表与循环双链表的区别

2.循环双链表的基本操作

封装综合

五、静态链表


一.线性表的基本操作

1.&表示C++语言中的引用调用

什么时候要传入参数的引用“&”--对参数的修改结果需要“带回来”

(1)未使用&时的代码

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

void test(int x){
    x=1024;
    printf("test函数内部x=%d\n",x);
}
int main()
{
    int x=1;
    printf("调用test之前x=%d\n",x);
    test(x);
    printf("调用test之后x=%d\n",x);
    return 0;
}

运行结果:

(2)使用&时的代码:

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

using namespace std;

void test(int &x){
    x=1024;
    printf("test函数内部x=%d\n",x);
}
int main()
{
    int x=1;
    printf("调用test之前x=%d\n",x);
    test(x);
    printf("调用test之后x=%d\n",x);
    return 0;
}

 运行效果:

二、顺序表的基本操作

 1.顺序表的静态分配

#define MaxSize 10            //定义线性表的最大长度

//ElemType可以是任何类型,如int,double......
typedef struct{
    ElemType data[MaxSize];  //顺序表的元素
    int length;              //顺序表的当前长度
}SqList;                     //顺序表的类型定义

(1)不进行初始化,会发生内存中会有遗留的“脏数据”

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10            //定义线性表的最大长度

using namespace std;


typedef struct{
    int data[MaxSize];  //顺序表的元素
    int length;              //顺序表的当前长度
}SqList;                     //顺序表的类型定义

void InitList(SqList  &L){
  //  for(int i=0;i<MaxSize;i++) //将数据初始化
   //     L.data[i]=0;
    L.length=0;             //顺序表的初始长度为0
}
int main()
{
    SqList L;               //声明一个顺序表
    InitList(L);            //初始化顺序表
    //尝试违规打印整个data数组
    for(int i=0;i<MaxSize;i++){
        printf("data[%d]=%d\n",i,L.data[i]);
    }
    return 0;
}

运行结果:

 (2)进行初始化

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10            //定义线性表的最大长度

using namespace std;


typedef struct{
    int data[MaxSize];  //顺序表的元素
    int length;              //顺序表的当前长度
}SqList;                     //顺序表的类型定义

void InitList(SqList  &L){
    for(int i=0;i<MaxSize;i++) //将数据初始化
       L.data[i]=0;
    L.length=0;             //顺序表的初始长度为0
}
int main()
{
    SqList L;               //声明一个顺序表
    InitList(L);            //初始化顺序表
    //尝试违规打印整个data数组
    for(int i=0;i<MaxSize;i++){
        printf("data[%d]=%d\n",i,L.data[i]);
    }
    return 0;
}

运行结果:

2.顺序表的动态分配

#define InitSize 10            //定义顺序表的初始长度

//ElemType可以是任何类型,如int,double......
typedef struct{
    ElemType *data;          //指示动态分配数组的指针
    int MaxSize;             //顺序表的最大容量
    int length;              //顺序表的当前长度
}SqList;                     //顺序表的类型定义(动态分配方式)

(1)key:动态申请和释放内存空间:

C语言---malloc、free函数

//malloc函数返回一个指针,需要强制转型为题目定义的数据元素类型指针
//malloc申请的是一整片连续的存储空间
L.data=(ElemType *)malloc(sizeof(ElemTye)*InitSize);

C++---new、delete关键字

L.data=new ElemType[InitSize];

(2)代码实现:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define InitSize 10            //定义线性表的最大长度
using namespace std;



typedef struct{
    int *data;          //指示动态分配数组的指针
    int MaxSize;             //顺序表的最大容量
    int length;              //顺序表的当前长度
}SqList;                     //顺序表的类型定义(动态分配方式)

void InitList(SqList  &L){
    //用malloc函数申请一篇连续的存储空间
    //L.data=(int *)malloc(InitSize*sizeof(int));
    L.data = new int[InitSize];
    L.length=0;
    L.MaxSize=InitSize;
}

void IncreaseSize(SqList &L,int len){
    int *p=L.data;
    //c语言版本
   // L.data=(int *)malloc((L.MaxSize+len)*sizeof(int));
    // C++版本
    L.data = new int[L.MaxSize + len];
    for(int i=0;i<L.MaxSize;i++){     //复制原来数组到新的数组
        L.data[i]=p[i];
    }
    L.MaxSize=L.MaxSize+len;
    //free(p);
    delete[] p; // 释放原来的内存空间
}
int main()
{
    SqList L;               //声明一个顺序表
    InitList(L);            //初始化顺序表
    printf("原来的数组长度%d\n",L.length);
    printf("原来的数组最大长度%d\n",L.MaxSize);
    IncreaseSize(L,5);
    printf("加长后的数组最大长度%d\n",L.MaxSize);
    return 0;
}

运行结果:

  3.顺序表的插入

(1)代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10            //定义线性表的最大长度
using namespace std;



typedef struct{
    int data[MaxSize];//用静态的“数组”存放数据元素
    int length;//顺序表的当前长度
}SqList;//顺序表的类型定义

void InitList(SqList  &L){
    for(int i=0;i<MaxSize;i++) //将数据初始化
       L.data[i]=0;
    L.length=0;             //顺序表的初始长度为0
}

bool ListInsert(SqList &L,int i,int e){//插入操作
    if(i<1||i>L.length+1){//输入数据的有效判断
        return false;
    }
    if(L.length>=MaxSize){
        return false;
    }
    for(int j=L.length;j>=i;j--)
        L.data[j]=L.data[j-1];
    L.data[i-1]=e;
    L.length++;
    return true;
}

int main(){
    SqList L;
    InitList(L);
    for(int i=0;i<5;i++){
        L.data[i]=i;
        ++L.length;
    }
    printf("原来length%d\n",L.length);
    for(int i=0;i<L.length;i++){
       printf("%d\t",L.data[i]);
    }
    printf("\n");
    if(ListInsert(L,3,3)){
        printf("插入成功!\n");
    }else{
        printf("输入数据有误\n");
    }
     printf("后来length%d\n",L.length);
      for(int i=0;i<L.length;i++){
       printf("%d\t",L.data[i]);
    }
    printf("\n");
    return 0;
}

运行结果:

4.线性表的删除

(1)代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10            //定义线性表的最大长度
using namespace std;



typedef struct{
    int data[MaxSize];//用静态的“数组”存放数据元素
    int length;//顺序表的当前长度
}SqList;//顺序表的类型定义

void InitList(SqList  &L){
    for(int i=0;i<MaxSize;i++) //将数据初始化
       L.data[i]=0;
    L.length=0;             //顺序表的初始长度为0
}

bool ListDelete(SqList &L,int i,int &e){//插入操作
    if(i<1||i>L.length){//输入数据的有效判断
        return false;
    }
    e=L.data[i-1];//i是数据的位序,i-1是数据的下标
    for(int j=i;j<L.length;j++)
        L.data[j-1]=L.data[j];
    L.length--;
    return true;
}

int main(){
    SqList L;
    InitList(L);
    int e=-1;
    for(int i=0;i<5;i++){
        L.data[i]=i;
        ++L.length;
    }
    printf("原来length%d\n",L.length);
    for(int i=0;i<L.length;i++){
       printf("%d\t",L.data[i]);
    }
    printf("\n");
    if(ListDelete(L,3,e)){
        printf("删除成功!\n");
    }else{
        printf("输入数据有误\n");
    }
     printf("后来length%d\n",L.length);
      for(int i=0;i<L.length;i++){
       printf("%d\t",L.data[i]);
    }
    printf("\n");
    printf("删除的数据为%d\n",e);
    return 0;
}

运行结果:

5.线性表的按位查找

 

6.线性表的按值查找

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10            //定义线性表的最大长度
using namespace std;



typedef struct{
    int data[MaxSize];//用静态的“数组”存放数据元素
    int length;//顺序表的当前长度
}SqList;//顺序表的类型定义

void InitList(SqList  &L){
    for(int i=0;i<MaxSize;i++) //将数据初始化
       L.data[i]=0;
    L.length=0;             //顺序表的初始长度为0
}

int LocateFind(SqList &L,int e){//按值查找回复位序
    for(int i=0;i<L.length;i++){
        if(L.data[i]==e){
            return i+1;
        }
    }
    return 0;//说明查找失败
}

int main(){
    SqList L;
    InitList(L);
    for(int i=0;i<5;i++){
        L.data[i]=i;
        ++L.length;
    }
    printf("length%d\n",L.length);
    for(int i=0;i<L.length;i++){
       printf("%d\t",L.data[i]);
    }
    printf("\n");
    printf("查找到的数据位序%d\n",LocateFind(L,3));
    return 0;
}

运行结果:

三、单链表的基本操作

1、用代码定义一个单链表

(1)定义单链表

typedef struct LNode{    //定义单链表节点类型
    ElemType data;       //每个节点存放一个数据元素,ElemType可为任意类型
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//使用LinkList强调这是个单链表,使用LNode *强调返回的是一个结点,二者意思一样,强调对象不同
LNode *GetElem(LinkList L,int i){
    int j=1;
    LNode *p=L->next;
    if(i==0)
        return L;
    if(i<1)
        return NULL;
    while(p!=NULL&&j<i){
        p=p->next;
        j++;
    }
    return p;
}

(2)不带头结点的单链表

typedef struct LNode{    //定义单链表节点类型
    ElemType data;       //每个节点存放一个数据元素,ElemType可为任意类型
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//初始化一个空的单链表
bool InitList(LinkList &L){
    L=NULL;         //空表,暂时还没有任何结点,防止脏数据
    return true;
}

void test(){
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    //初始化一个空表
    InitList(L);
    //后续代码.....
}

//判断单链表是否为空
bool Empty(LinkList L){
    return (L==NULL);
}

(3)带头结点的单链表

typedef struct LNode{    //定义单链表节点类型
    ElemType data;       //每个节点存放一个数据元素,ElemType可为任意类型
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//初始化一个空的单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NULL)                      //内存不足,分配失败
        return false;
    L->next=NULL;                    //头结点之后暂时还没有结点
    return true;
}

void test(){
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    //初始化一个空表
    InitList(L);
    //后续代码.....
}

2.按位序插入

(1)带头结点按位序插入

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//初始化一个空的单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NULL)                      //内存不足,分配失败
        return false;
    L->next=NULL;                    //头结点之后暂时还没有结点
    return true;
}


int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L->next;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }

    }else{
        printf("插入失败\n");
    }
    return 0;
}

运行结果:

 (2)不带头结点按位序插入

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    if(i==1){//插入第一个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;        //头指针指向新结点
        return true;
    }
    LNode *p;       //指针p指向当前扫描到的结点
    int j=1;        //表示当前指针p指向的是第几个结点,不带头结点从1开始
    p = L;          //L指向头结点,头结点是第1个结点
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
    L=NULL;                   //空表
    return true;
}


int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
    return 0;
}

运行结果:

3.指定结点的插入操作

(1)指定结点的后插操作

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    if(i==1){//插入第一个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;        //头指针指向新结点
        return true;
    }
    LNode *p;       //指针p指向当前扫描到的结点
    int j=1;        //表示当前指针p指向的是第几个结点,不带头结点从1开始
    p = L;          //L指向头结点,头结点是第1个结点
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
    L=NULL;                   //空表
    return true;
}

//在P节点之后插入元素
bool InsertNextNode(LNode *p,int e){
    if(p==NULL)
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
    printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点后输入:");
    scanf("%d",&n);
    LNode *p=L;
    int j=1;
    while(p!=NULL&&j<n-1){
            p=p->next;
            j++;
    }
    if(p==NULL){
        printf("你的输入不正确");
    }
    if(InsertNextNode(p,100)){
        printf("指定节点后插成功\n");
    }
    else{
        printf("指定节点后插失败\n");
    }
    LNode *s=L;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
    return 0;
}

运行结果:

 (2)带头结点的指定位置的后插操作

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}


//初始化一个空的单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NULL)                      //内存不足,分配失败
        return false;
    L->next=NULL;                    //头结点之后暂时还没有结点
    return true;
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L->next;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
    printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点后输入:");
    scanf("%d",&n);
    if(ListInsert(L,n+1,100)){
        printf("指定节点后插成功\n");
    }
    else{
        printf("指定节点后插失败\n");
    }
    LNode *s=L->next;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
    return 0;
}

运行结果:

 (3)不带头节点的指定位置后插操作

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    if(i==1){//插入第一个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;        //头指针指向新结点
        return true;
    }
    LNode *p;       //指针p指向当前扫描到的结点
    int j=1;        //表示当前指针p指向的是第几个结点,不带头结点从1开始
    p = L;          //L指向头结点,头结点是第1个结点
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
    L=NULL;                   //空表
    return true;
}


int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点后输入:");
    scanf("%d",&n);
    if(ListInsert(L,n+1,100)){
        printf("指定节点后插成功\n");
    }
    else{
        printf("指定节点后插失败\n");
    }
    LNode *s=L;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
    return 0;
}

运行结果:

 (4)带头结点指定节点的前插操作

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//初始化一个空的单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NULL)                      //内存不足,分配失败
        return false;
    L->next=NULL;                    //头结点之后暂时还没有结点
    return true;
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L->next;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
    printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点前输入:");
    scanf("%d",&n);
    if(ListInsert(L,n,100)){
        printf("指定节点前插成功\n");
    }
    else{
        printf("指定节点前插失败\n");
    }
    LNode *s=L->next;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
    return 0;
}

运行结果:

 (5)不带头节点的前插操作

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    if(i==1){//插入第一个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;        //头指针指向新结点
        return true;
    }
    LNode *p;       //指针p指向当前扫描到的结点
    int j=1;        //表示当前指针p指向的是第几个结点,不带头结点从1开始
    p = L;          //L指向头结点,头结点是第1个结点
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
    L=NULL;                   //空表
    return true;
}


int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点前输入:");
    scanf("%d",&n);
    if(ListInsert(L,n,100)){
        printf("指定节点前插成功\n");
    }
    else{
        printf("指定节点前插失败\n");
    }
    LNode *s=L;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
    return 0;
}

运行结果:

 (6)指定结点的前插操作(采用交换覆盖的方法)

//前插操作,在p结点之前插入结点
bool InsertPriorNode(LNode *p,LNode *s){
    if(p==NULL || s==NULL){
        return false;
    }
    s->next=p->next;
    p->next=s;
    int temp=p->data;
    p->data=s->data;
    s->data=temp;
    return true;
}

4.按位序删除

(1)带头结点的按位序删除

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
    if(i<1)
        return false;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点,不带头结点从1开始
    p = L;          //L指向头结点,头结点是第1个结点
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    if(p->next==NULL)//第i-1个结点之后已无其它结点
        return false;
    LNode *q=p->next;//令q指向被删除的结点
    e=q->data;//用e返回被删除的元素
    p->next=q->next;//将*q结点从链中断开
    free(q);
    return true;//插入成功
}


//初始化一个空的单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NULL)                      //内存不足,分配失败
        return false;
    L->next=NULL;                    //头结点之后暂时还没有结点
    return true;
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    int e=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L->next;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
    printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入删除的结点位序:");
    scanf("%d",&n);
    if(ListDelete(L,n,e)){
        printf("指定节点删除成功:%d\n",e);
    }
    else{
        printf("指定节点删除失败\n");
    }
    LNode *s=L->next;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
    return 0;
}

运行结果:

(2)不带头结点按位序删除

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    if(i==1){//插入第一个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;        //头指针指向新结点
        return true;
    }
    LNode *p;       //指针p指向当前扫描到的结点
    int j=1;        //表示当前指针p指向的是第几个结点,不带头结点从1开始
    p = L;          //L指向头结点,头结点是第1个结点
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;//插入成功
}

//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
    if(i<1)
        return false;
    if(i==1){//删除第一个结点的操作与其他结点操作不同
        e=L->data;
        L=L->next;//头指针指向新结点
        return true;
    }
    LNode *p;       //指针p指向当前扫描到的结点
    int j=1;        //表示当前指针p指向的是第几个结点,不带头结点从1开始
    p = L;          //L指向头结点,头结点是第1个结点
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    if(p->next==NULL)//第i-1个结点之后已无其它结点
        return false;
    LNode *q=p->next;//令q指向被删除的结点
    e=q->data;//用e返回被删除的元素
    p->next=q->next;//将*q结点从链中断开
    free(q);
    return true;//插入成功
}

//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
    L=NULL;                   //空表
    return true;
}



int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    int e=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入删除的结点位序:");
    scanf("%d",&n);
    if(ListDelete(L,n,e)){
        printf("指定节点删除成功:%d\n",e);
    }
    else{
        printf("指定节点删除失败\n");
    }
    LNode *s=L;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
    return 0;
}

运行结果:

 (3)指定节点的删除

若p刚好是最后一个结点,会出现空指针错误

//删除结点p
bool DeleteNode(LNode *p){
    if(p==NULL)
        return false;
     LNode *q=p->next;//令q指向被删除的结点
    e=q->data;//用e返回被删除的元素
    p->next=q->next;//将*q结点从链中断开
    free(q);
    return true;
}

5.封装综合

按位查找或者按值查找并进行封装删除,后插,前插,求表长操作

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//按位查找
LNode *GetElem(LinkList L,int i){
    if(i<0)
        return NULL;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    return p;
}

//按值查找
LNode *LocateElem(LinkList L,int e){
    LNode *p=L->next;
    //从第一个结点开始查找数据域为e的结点
    while(p!=NULL&&p->data!=e)
        p=p->next;
    return p;//找到后返回该结点指针,否则返回NULL
}

//删除结点p
bool DeleteNode(LNode *p,int &e){
    if(p==NULL)
        return false;
     LNode *q=p->next;//令q指向被删除的结点
    e=q->data;//用e返回被删除的元素
    p->next=q->next;//将*q结点从链中断开
    free(q);
    return true;
}

//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i);//找到第i-1个结点
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    if(p->next==NULL)//第i-1个结点之后已无其它结点
        return false;
    return DeleteNode(p,e);
}

//前插操作,在p结点之前插入结点
bool InsertPriorNode(LNode *p,int e){
    if(p==NULL){
        return false;
    }
    LNode *s=(LNode *)malloc(sizeof(LNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    int temp=p->data;
    p->data=s->data;
    s->data=temp;
    return true;
}

//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int e){
    if(p==NULL)
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;
}


//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i);//找到第i个结点
    return InsertNextNode(p,e);//插入成功
}

//在第i个位置前插入元素e
bool ListInsertPrior(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i+1);//找到第i个结点
    return InsertPriorNode(p,e);//插入成功
}


//求表的长度
int Length(LinkList L){
    int len=0;
    LNode *p=L;
    while(p->next!=NULL){
        p=p->next;
        len++;
    }
    return len;
}


//输出函数
void print(LinkList L){
    LNode *s=L->next;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
}

//初始化一个空的单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NULL)                      //内存不足,分配失败
        return false;
    L->next=NULL;                    //头结点之后暂时还没有结点
    return true;
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    int n=0;
    int e=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L->next;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点后输入:");
    scanf("%d",&n);
    if(ListInsertNext(L,n+1,100)){
        printf("指定节点后插成功\n");
    }
    else{
        printf("指定节点后插失败\n");
    }
    print(L);
    n=0;
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点前输入:");
    scanf("%d",&n);
    if(ListInsertPrior(L,n,100)){
        printf("指定节点前插成功\n");
    }
    else{
        printf("指定节点前插失败\n");
    }
    print(L);
    n=0;
    printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入删除的结点位序:");
    scanf("%d",&n);
    if(ListDelete(L,n,e)){
        printf("指定节点删除成功:%d\n",e);
    }
    else{
        printf("指定节点删除失败\n");
    }
    print(L);
    printf("\n");
    printf("表的长度:%d",Length(L));
    return 0;
}

运行结果:

 6.尾插法建立单链表

(1)带头结点尾插法

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//按位查找第i-1个结点
LNode *GetElem(LinkList L,int i){
    if(i<0)
        return NULL;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    return p;
}

//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int e){
    if(p==NULL)
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;
}


//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i);//找到第i个结点
    return InsertNextNode(p,e);//插入成功
}



//输出函数
void print(LinkList L){
    LNode *s=L->next;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
}

//初始化一个空的单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NULL)                      //内存不足,分配失败
        return false;
    L->next=NULL;                    //头结点之后暂时还没有结点
    return true;
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L->next;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    return 0;
}

运行结果:

(2)不带头节点的尾插法

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//按位查找第i-1个结点
LNode *GetElem(LinkList L,int i){
    LNode *p;       //指针p指向当前扫描到的结点
    int j=1;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p!=NULL&&j<i-1){//循环找到第i-个结点
        p=p->next;
        j++;
    }
    return p;
}

//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int e){
    if(p==NULL)
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;
}


//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
    if(i<1)
        return false;
    if(i==1){//插入第一个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;        //头指针指向新结点
        return true;
    }
    LNode *p=GetElem(L,i);//找到第i个结点
    return InsertNextNode(p,e);//插入成功
}



//输出函数
void print(LinkList L){
    LNode *s=L;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
}

//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
    L=NULL;                   //空表
    return true;
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L;
        while(s){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    return 0;
}

 运行结果:

 7.头插法建立单链表

(1)带头结点头插法

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;


LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
    LNode *s;
    int x;
    L=(LinkList)malloc(sizeof(LNode));//创建头结点
    L->next=NULL;
    printf("输入结点的值(9999视为退出):\n");
    scanf("%d",&x);//输入结点的值
    while(x!=9999){
        s=(LNode *)malloc(sizeof(LNode));//创建新结点
        s->data=x;
        s->next=L->next;
        L->next=s;//将新结点插入表中,L为头指针
        scanf("%d",&x);
    }
    return L;
}

//求表的长度
int Length(LinkList L){
    int len=0;
    LNode *p=L;
    while(p->next!=NULL){
        p=p->next;
        len++;
    }
    return len;
}

//输出函数
void print(LinkList L){
    LNode *s=L->next;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    L=List_HeadInsert(L);
    printf("单链表L:\n");
    print(L);
    printf("\n");
    printf("表的长度:%d",Length(L));
    return 0;
}

运行结果:

 (2)不带头结点头插法

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;


LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
    LNode *s;
    int x;
    L=NULL;//建立一个空的没有头结点的单链表
    printf("输入结点的值(9999视为退出):\n");
    scanf("%d",&x);//输入结点的值
    while(x!=9999){
        s=(LNode *)malloc(sizeof(LNode));//创建新结点
        s->data=x;
        s->next=L;
        L=s;
        scanf("%d",&x);
    }
    return L;
}

//求表的长度
int Length(LinkList L){
    int len=1;//从第一个开始,因为他没有头结点
    LNode *p=L;
    while(p->next!=NULL){
        len++;
        p=p->next;

    }
    return len;
}

//输出函数
void print(LinkList L){
    LNode *s=L;
    while(s){
        printf("%d\t",s->data);
        s=s->next;
    }
}

int main()
{
    LinkList L;     //此处为声明一个指向单链表的指针,但是并没有创建一个结点
    L=List_HeadInsert(L);
    printf("单链表L:\n");
    print(L);
    printf("\n");
    printf("表的长度:%d",Length(L));
    return 0;
}

运行结果:

 8.循环单链表

封装综合

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

using namespace std;

typedef struct LNode{    //定义单链表节点类型
    int data;       //每个节点存放一个数据元素
    struct LNode *next;  //指针指向下一个节点
}LNode,*LinkList;

//初始化一个循环单链表
bool InitList(LinkList &L){
    L = (LNode *)malloc(sizeof(LNode));//建立一个头结点
    if(L==NULL)
        return false;
    L->next=L;//头结点next指向头结点
    return true;
}

//判断循环单链表是否为空
bool Empty(LinkList &L){
    if(L->next==L){
        return true;
    }
    else
        return false;
}

//判断p结点是否是循环单链表的尾结点
bool isTail(LinkList L,LNode *p){
    if(p->next==L){
        return true;
    }
    else
        return false;
}


//按位查找i-1位
LNode *GetElem(LinkList L,int i){
    if(i<0)
        return NULL;
    LNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p->next!=L&&j<i-1){//循环找到第i-1个结点
        p=p->next;
        j++;
    }
    return p;
}

//按值查找
LNode *LocateElem(LinkList L,int e){
    LNode *p=L->next;
    //从第一个结点开始查找数据域为e的结点
    while(p->next!=L&&p->data!=e)
        p=p->next;
    return p;//找到后返回该结点指针,否则返回NULL
}

//删除结点p的后继结点
bool DeleteNode(LNode *p,int &e){
    if(p==NULL)
        return false;
     LNode *q=p->next;//令q指向被删除的结点
    e=q->data;//用e返回被删除的元素
    p->next=q->next;//将*q结点从链中断开
    free(q);
    return true;
}

//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i);//找到第i-1个结点
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    if(p->next==NULL)//第i-1个结点之后已无其它结点
        return false;
    return DeleteNode(p,e);
}

//前插操作,在p结点之前插入结点
bool InsertPriorNode(LNode *p,int e){
    if(p==NULL){
        return false;
    }
    LNode *s=(LNode *)malloc(sizeof(LNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    int temp=p->data;
    p->data=s->data;
    s->data=temp;
    return true;
}

//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int e){
    if(p==NULL)
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;
}


//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i);//找到第i-1个结点
    return InsertNextNode(p,e);//插入成功
}

//在第i个位置前插入元素e
bool ListInsertPrior(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i+1);//找到第i个结点
    return InsertPriorNode(p,e);//插入成功
}


//求表的长度
int Length(LinkList L){
    int len=0;
    LNode *p=L;
    while(p->next!=L){
        p=p->next;
        len++;
    }
    return len;
}


//输出函数
void print(LinkList L){
    LNode *s=L->next;
    while(s->next!=L->next){
        printf("%d\t",s->data);
        s=s->next;
    }
}

int main()
{
    LinkList L;     //此处为声明一个指向循环单链表的指针,但是并没有创建一个结点
    int n=0;
    int e=0;
    //初始化一个空表
    if(InitList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
        printf("插入成功!\n");
        LNode *s=L->next;
        while(s->next!=L->next){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点后输入:");
    scanf("%d",&n);
    if(ListInsertNext(L,n+1,100)){
        printf("指定节点后插成功\n");
    }
    else{
        printf("指定节点后插失败\n");
    }
    print(L);
    n=0;
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点前输入:");
    scanf("%d",&n);
    if(ListInsertPrior(L,n,100)){
        printf("指定节点前插成功\n");
    }
    else{
        printf("指定节点前插失败\n");
    }
    print(L);
    n=0;
    printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入删除的结点位序:");
    scanf("%d",&n);
    if(ListDelete(L,n,e)){
        printf("指定节点删除成功:%d\n",e);
    }
    else{
        printf("指定节点删除失败\n");
    }
    print(L);
    printf("\n");
    printf("表的长度:%d",Length(L));
    return 0;
}

运行结果:

四、双链表的基本操作

1.双链表与循环双链表的区别

双链表

表头结点的prior指向NULL;

表尾结点的next指向NULL。

循环双链表

表头结点的prior指向表尾结点;

表尾结点的next指向头结点。

2.循环双链表的基本操作

封装综合

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

using namespace std;

//定义一个双链表
typedef struct DNode{
    int data;
    struct DNode *prior,*next;
}DNode,*DLinkList;

//初始化空的循环双链表
bool InitDLinkList(DLinkList &L){
    L = (DNode *)malloc(sizeof(DNode));//分配一个头结点
    if(L==NULL)
        return false;
    //头结点的prior和next都指向头结点
    L->prior=L;
    L->next=L;
    return true;
}

//判断循环双链表是否为空
bool Empty(DLinkList L){
    if(L->next==L)
        return true;
    else
        return false;
}

//判断结点p是否为循环双链表的表尾结点
bool isTail(DLinkList L,DNode *p){
    if(p->next==L)
        return true;
    else
        return false;
}

//按位查找i-1位
DNode *GetElem(DLinkList L,int i){
    if(i<0)
        return NULL;
    DNode *p;       //指针p指向当前扫描到的结点
    int j=0;        //表示当前指针p指向的是第几个结点
    p = L;          //L指向头结点,头结点是第0个结点(不存数据)
    while(p->next!=L&&j<i-1){//循环找到第i-1个结点
        p=p->next;
        j++;
    }
    return p;
}

//删除结点p的后继结点
bool DeleteDNode(DNode *p,DNode *q,int &e){
    if(p==NULL)
        return false;
    p->next=q->next;
    e=q->data;//用e返回被删除的元素
    q->next->prior=p;//将*q结点从链中断开
    free(q);
    return true;
}

//在第i个位置删除元素e
bool ListDelete(DLinkList &L,int i,int &e){
    if(i<1)
        return false;
    DNode *p=GetElem(L,i);//找到第i-1个结点
    DNode *q=p->next;
    if(p==NULL)     //i值不合法,i大于链表长度
        return false;
    return DeleteDNode(p,q,e);
}



//后插操作,在P节点之后插入元素
bool InsertNextNode(DNode *p,int e){
    if(p==NULL)
        return false;
    DNode *s=(DNode *)malloc(sizeof(DNode));
    //内存分配失败
    if(s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next->prior=s;
    s->prior=p;
    p->next=s;
    return true;
}

//在第i个位置插入元素e
bool ListInsertNext(DLinkList &L,int i,int e){
    if(i<1)
        return false;
    DNode *p=GetElem(L,i);//找到第i-1个结点
    return InsertNextNode(p,e);//插入成功
}

//求表的长度
int Length(DLinkList L){
    int len=0;
    DNode *p=L;
    while(p->next!=L){
        p=p->next;
        len++;
    }
    return len;
}

//输出函数
void print(DLinkList L){
    DNode *s=L->next;
    while(s->next!=L->next){
        printf("%d\t",s->data);
        s=s->next;
    }
}

int main()
{
   //初始化一个循环双链表
   DLinkList L;
   int n=0;
   int e=0;
   //初始化一个空表
    if(InitDLinkList(L))
        printf("初始化成功");
    printf("\n");
    //后续代码.....
    if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
        printf("插入成功!\n");
        DNode *s=L->next;
        while(s->next!=L->next){
            printf("%d\t",s->data);
            s=s->next;
        }
    }else{
        printf("插入失败\n");
    }
     printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入在第几个节点后输入:");
    scanf("%d",&n);
    if(ListInsertNext(L,n+1,100)){
        printf("指定节点后插成功\n");
    }
    else{
        printf("指定节点后插失败\n");
    }
    print(L);
     n=0;
    printf("\n");
    //在第n个节点后面插入元素e
    printf("请输入删除的结点位序:");
    scanf("%d",&n);
    if(ListDelete(L,n,e)){
        printf("指定节点删除成功:%d\n",e);
    }
    else{
        printf("指定节点删除失败\n");
    }
    print(L);
    printf("\n");
    printf("表的长度:%d",Length(L));
    return 0;
}

运行结果:

五、静态链表

#define MaxSize 10  //静态链表的最大长度
typedef struct{     //静态链表结构类型的定义
    ElemType data;  //存储数据元素
    int next;       //下一个元素的数组下标
}SLinkList[MaxSize]

  • 13
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值