考研一轮线表链式存储完全实现含测试效果(王卓版)

博文源于王卓老师的数据结构实现版本并做了测试,有需要的读者可以收藏。

1、线性表的链式存储结构

typedef struct LNode{
    
    
    ElementType data;
    struct LNode*next;
}LNode,*LinkList;

2、初始化链表

初始化链表就是分配内存,设置为Next为null

Status InitList(LinkList &L){
    
    
    L = new LNode; //生成新结点作为头结点,用头指针L指向头结点
    L->next= NULL; //头结点的指针值为空
    return OK;
}

3、头插法创建链表

头插法创建链表主要是针对L的next指向新创建结点。

void CreateList_T(LinkList &L,int n){
    
    
    L = new LNode;
    L->next = NULL;
    LinkList r = L;
    for(int i =0;i<n;i++){
    
    
        LinkList  p = new LNode; // 生成新结点
        cin >> p->data;  //输入元素赋给新结点*p 的数据域
        p->next = NULL; //将新结点*p 插入尾结点*r 之后
        r->next = p;
        r = p; //r指向新的尾结点
    }
}

4、尾插法创建链表

尾部插入主要要有一个尾指针。

void CreateList_H(LinkList &L,int n){
    
    
    //逆位序输入n个元素的值,建立带表头结点的单链表L
    L = new LNode;
    L->next = NULL;
    for(int i=0;i<n;i++){
    
    
        LinkList  p = new LNode;
        cin >> p->data;
        p->next = L->next;
        L->next = p;

    }

}

5、链表插入

  • 1、查找结点a_(i-1) 并由指针p指向该结点
  • 2、生成1个新结点s
  • 3、将新结点*s 数据域置为e
  • 4、将新结点*s 的指针域指向结点a_i
  • 5、将结点*p 的指针域指向新结点s
Status ListInsert(LinkList &L,int i,ElementType e){
    
    
    LinkList  p = L;
    int j = 0;
    while(p && j<i-1){
    
    
        p = p->next;
        j++;
    }
    if(!p || j>i-1) return ERROR;//查找第i-1个新结点,p指向该节点
    LNode* s = new LNode;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}

6、 链表删除第一个值

  • 1、查找结点a_(i-1) 并由指针p指向该节点
  • 2、临时保存待删除节点a_i 的地址在q中,以备释放
  • 3、将结点*p 的指针域指向a_i的直接后继结点
  • 4、释放结点a_i的空间
Status ListDelete(LinkList &L,int i){
    
    
    //带头结点的单链表L中,删除第i个元素
    LinkList p = L;
    int j =0;
    while((p->next) && j<i-1){
    
    
        p = p->next;
        j++;
    }
    if(!(p->next) || (j>i-1)) return ERROR;
    LNode *q = p->next;
    p->next = q->next;
    delete q;
    return OK;
}

7、链表打印(补充)

打印一下整个链表,一跳一跳

void Print(LinkList L){
    
    
    LinkList  p = L->next;
    while(p){
    
    
        cout << p->data << " ";
        p=p->next;
    }
    cout << endl;
}

8、获取第i个链表的值

这也是与链表打印有着相同的原理。

Status GetElem(LinkList L,int i,ElementType &e){
    
    
    LinkList p = L->next; //指向第一号结点
    int j =1; //第一位
    while(p && j<i){
    
    
        p=p->next;
        j++;
    }
    if(!p || j>i) return ERROR; //i值不合法,i>n 或i<=0
    e = p->data;//取第i个结点的数据域
    return OK;
}

9、查找元素e是否存在

跟链表打印相似

LNode *LocateElem(LinkList L,ElementType e){
    
    
    LinkList  p = L->next;
    while(p && p->data!=e){
    
     //如果data不是那就往后跳,跳到p为空
        p=p->next;
    }
    return p; //查找成功返回p,否则返回NULL
}

10、链表是否为空(补充,自己测试用)

判断L就行了

Status IsEmpty(LinkList L){
    
    
    if(L->next){
    
    
        return FALSE;
    }else return TRUE;
}

测试效果

在这里插入图片描述

完整代码

#include<iostream>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define MAXSIZE 10
using namespace std;
typedef int Status;
typedef int ElementType;

//线性表的顺序存储
typedef struct LNode{
    
    
    ElementType data;
    struct LNode*next;
}LNode,*LinkList;

Status InitList(LinkList &L){
    
    
    L = new LNode; //生成新结点作为头结点,用头指针L指向头结点
    L->next= NULL; //头结点的指针值为空
    return OK;
}

Status IsEmpty(LinkList L){
    
    
    if(L->next){
    
    
        return FALSE;
    }else return TRUE;
}

Status GetElem(LinkList L,int i,ElementType &e){
    
    
    LinkList p = L->next; //指向第一号结点
    int j =1; //第一位
    while(p && j<i){
    
    
        p=p->next;
        j++;
    }
    if(!p || j>i) return ERROR; //i值不合法,i>n 或i<=0
    e = p->data;//取第i个结点的数据域
    return OK;
}
LNode *LocateElem(LinkList L,ElementType e){
    
    
    LinkList  p = L->next;
    while(p && p->data!=e){
    
     //如果data不是那就往后跳,跳到p为空
        p=p->next;
    }
    return p; //查找成功返回p,否则返回NULL
}
/*单链表的插入
 * 1、查找结点a_(i-1) 并由指针p指向该结点
 * 2、生成1个新结点s
 * 3、将新结点*s 数据域置为e
 * 4、将新结点*s 的指针域指向结点a_i
 * 5、将结点*p 的指针域指向新结点s
 * */
Status ListInsert(LinkList &L,int i,ElementType e){
    
    
    LinkList  p = L;
    int j = 0;
    while(p && j<i-1){
    
    
        p = p->next;
        j++;
    }
    if(!p || j>i-1) return ERROR;//查找第i-1个新结点,p指向该节点
    LNode* s = new LNode;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}
/*单链表的删除
 * 1、查找结点a_(i-1) 并由指针p指向该节点
 * 2、临时保存待删除节点a_i 的地址在q中,以备释放
 * 3、将结点*p 的指针域指向a_i的直接后继结点
 * 4、释放结点a_i的空间
 * */

Status ListDelete(LinkList &L,int i){
    
    
    //带头结点的单链表L中,删除第i个元素
    LinkList p = L;
    int j =0;
    while((p->next) && j<i-1){
    
    
        p = p->next;
        j++;
    }
    if(!(p->next) || (j>i-1)) return ERROR;
    LNode *q = p->next;
    p->next = q->next;
    delete q;
    return OK;
}
void CreateList_H(LinkList &L,int n){
    
    
    //逆位序输入n个元素的值,建立带表头结点的单链表L
    L = new LNode;
    L->next = NULL;
    for(int i=0;i<n;i++){
    
    
        LinkList  p = new LNode;
        cin >> p->data;
        p->next = L->next;
        L->next = p;

    }

}
void Print(LinkList L){
    
    
    LinkList  p = L->next;
    while(p){
    
    
        cout << p->data << " ";
        p=p->next;
    }
    cout << endl;
}
void CreateList_T(LinkList &L,int n){
    
    
    L = new LNode;
    L->next = NULL;
    LinkList r = L;
    for(int i =0;i<n;i++){
    
    
        LinkList  p = new LNode; // 生成新结点
        cin >> p->data;  //输入元素赋给新结点*p 的数据域
        p->next = NULL; //将新结点*p 插入尾结点*r 之后
        r->next = p;
        r = p; //r指向新的尾结点
    }
}
int main(){
    
    
    LinkList  L;
    InitList(L);
    cout << "After init is L empty?:" << IsEmpty(L) << endl;
    ListInsert(L,1,1);
    ElementType e;
    GetElem(L,1,e);
    cout << "After insert,get elem is :"<< e << endl;
    LinkList  p = LocateElem(L,1);
    cout << "search 1,is in?:" << p->data << endl;
    ListDelete(L,1);
    cout << "after delete is L empty?:" << IsEmpty(L) << endl;
    CreateList_H(L,5);
    cout << "head insert:" << endl;
    Print(L);
    CreateList_T(L,5);
    cout << "tail insert:" << endl;
    Print(L);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37149062/article/details/123458696