【数据结构】线性表(WD)

顺序表的实现——静态分配

#include <bits/stdc++.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
}

//在L的位序i处插入元素e
bool BoolListInsert(SqList &L, int i, int e)
{
    if (i < 1 || i > L.length + 1)
    { //判断i的范围是否有效
        return false;
    }
    if (L.length >= MaxSize)
    { //当前存储空间已满,不能插入
        return false;
    }
    for (int j = L.length; j >= i; j--)
    { //将第i个元素及之后的元素后移
        L.data[j] = L.data[j - 1];
    }
    L.data[i - 1] = e; //在位置i处放入e
    L.length++;        //更新长度
    return true;
}

//删除位序i处的元素,并用e返回
bool ListDelete(SqList &L, int i, int &e)
{
    if (i < 1 || i > L.length)
    { //判断i的范围是否有效
        return false;
    }
    e = L.data[i - 1];                 //将被删除的元素赋值给e
    for (int j = i; j < L.length; j++) //将第i个元素后的元素前移
    {
        L.data[j - 1] = L.data[j];
    }
    L.length--; //更新长度
    return true;
}

//在顺序表L中查找第一个元素值等于e的元素,并返回其位序
int LocateElem(SqList &L, int e)
{
    for (int i = 0; i < L.length; i++)
    {
        if (L.data[i] == e)
        {
            return i + 1; //返回位序
        }
    }
    return 0; //查找失败
}

//打印函数
void print(SqList &L)
{
    for (int i = 0; i < L.length; i++)
    {
        printf("data[%d]=%d\n", i, L.data[i]);
    }
}

int main()
{
    SqList L; //声明一个顺序表

    InitList(L); //初始化顺序表

    //向线性表中填充元素
    for (int i = 0; i < 5; i++)
    {
        L.data[i] = i + 1;
        L.length++;
    }

    printf("Initial content of linear table:\n");
    print(L);

    if (BoolListInsert(L, 3, 123))
    { //插入元素成功
        printf("Insert element 123 successfully!\n");
        printf("The updated linear table is:\n");
        print(L);
    }
    else
    { //插入元素失败
        printf("Failed to insert. Please check the validity of the element!");
    }

    int e = -1; //用变量e把删除的元素“带回来”

    if (ListDelete(L, 3, e))
    { //删除元素成功
        printf("Element %d removed successfully!\n", e);
        printf("The updated linear table is:\n");
    }
    else
    { //删除元素失败
        printf("Deletion failed!\n");
    }

    print(L);

    int loc = LocateElem(L, 2);

    if (loc)
    { //查找元素成功
        printf("The order of element 2 is=%d\n", loc);
    }
    else
    { //查找元素失败
        printf("Element 2 not found\n");
    }

    return 0;
}

output
Initial content of linear table:
data[0]=1
data[1]=2
data[2]=3
data[3]=4
data[4]=5
Insert element 123 successfully!
The updated linear table is:
data[0]=1
data[1]=2
data[2]=123
data[3]=3
data[4]=4
data[5]=5
Element 123 removed successfully!
The updated linear table is:
data[0]=1
data[1]=2
data[2]=3
data[3]=4
data[4]=5
The order of element 2 is=2

顺序表的实现——动态分配

#include <bits/stdc++.h>

#define InitSize 10 //默认的最大长度

using namespace std;

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

//初始化顺序表
void InitList(SeqList &L)
{
    //用malloc函数申请一片连续的存储空间
    L.data = (int *)malloc(InitSize * sizeof(int));
    L.MaxSize = InitSize;
    L.length = 0;
}

//增加动态数组的长度
void IncreaseSize(SeqList &L, int len)
{
    int *p = L.data;
    L.data = (int *)malloc((L.MaxSize + len) * sizeof(int));
    // for (int i = 0; i < L.MaxSize; i++)
    // {
    //     L.data[i] = p[i]; //将数据复制到新区域
    // }
    L.MaxSize = L.MaxSize + len; //更新顺序表最大长度
    free(p);                     //释放原来的内存空间
}

int main()
{
    SeqList L; //声明一个顺序表

    InitList(L); //初始化顺序表

    cout << L.MaxSize << endl;

    IncreaseSize(L, 5);

    cout << L.MaxSize << endl;

    return 0;
}

output
10
15

单链表——不带头结点

#include <bits/stdc++.h>

using namespace std;

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

//LNode强调返回的是一个结点
//LinkList强调这是一个单链表

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

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

//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p, int e)
{
    if (p == NULL)
    { //i值不合法
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if (s == NULL)
    { //内存分配失败
        return false;
    }
    s->data = e; //用结点s保存数据元素e
    s->next = p->next;
    p->next = s; //将结点s连到p之后
    return true; //插入成功
}

//在第i个位置插入元素e(不带头结点)
bool ListInsert(LinkList &L, int i, int e)
{
    if (i < 1)
    {
        return false;
    }

    if (i == 1)
    { //插入第1个结点的操作与其他结点操作不同
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data = e;
        s->next = L;
        L = s; //头指针指向新结点
        return true;
    }

    LNode *p;  //指针p指向当前扫描到的结点
    int j = 1; //当前p指向的是第几个结点
    p = L;     //p指向第1个结点(不是头结点)

    while (p != NULL && j < i - 1)
    { //循环找到第i-1个结点
        p = p->next;
        j++;
    }
    InsertNextNode(p,e);
    return true;
}

//打印函数(不带头结点)
void print(LinkList &L)
{
    LNode *p = L;

    while (p != NULL)
    {
        if (p->next != NULL)
        {
            printf("%d->", p->data);
        }
        else
        {
            printf("%d", p->data);
        }
        p = p->next;
    }
    printf("\n");
}


int main()
{
    LinkList L; //声明一个指向单链表的指针

    InitList(L); //初始化一个空表

    if (Empty(L))
    {
        ListInsert(L, 1, 1);
        ListInsert(L, 2, 2);
        ListInsert(L, 3, 3);
    }
    else
    {
        printf("failure!\n");
    }
    print(L);

    return 0;
}

output

1->2->3

单链表——带头结点

#include <bits/stdc++.h>

using namespace std;

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

//LNode强调返回的是一个结点
//LinkList强调这是一个单链表

//初始化一个单链表(带头结点)
bool InitList(LinkList &L)
{
    L = (LNode *)malloc(sizeof(LNode)); //分配一个头结点
    if (L == NULL)
    { //内存不足,分配失败
        return false;
    }
    else
    {
        L->next = NULL; //头结点之后暂时还没有结点
        //养成好习惯,只要是初始化单链表,都先把头指针指向NULL
    }
    return true;
}

//判断单链表是否为空(带头结点)
bool Empty(LinkList L)
{
    return (L->next == NULL);
}

//前插操作:在p结点之前插入元素e
bool InsertPriorNode(LNode *p, int e)
{
    if (p == NULL)
    { //i值不合法
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if (s == NULL)
    { //内存分配失败
        return false;
    }
    s->next = p->next;
    p->next = s;       //将新结点s连到p之后
    s->data = p->data; //将p中元素复制到s中
    p->data = e;       //p中元素覆盖为e
    return true;       //插入成功
}

//前插操作:在p结点之前插入结点s
bool InsertPriorNode(LNode *p, LNode *s)
{
    if (p == NULL || s == NULL)
    { //i值不合法
        return false;
    }
    s->next = p->next;
    p->next = s;        //s连到p之后
    int temp = p->data; //交换数据域部分
    p->data = s->data;
    s->data = temp;
    return true;
}

//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p, int e)
{
    if (p == NULL)
    { //i值不合法
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if (s == NULL)
    { //内存分配失败
        return false;
    }
    s->data = e; //用结点s保存数据元素e
    s->next = p->next;
    p->next = s; //将结点s连到p之后
    return true; //插入成功
}

//按位查找,返回第i个元素(带头结点)
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)
    { //循环找到第i个结点
        p = p->next;
        j++;
    }
    return p;
}

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

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

//尾插法正向建立单链表
LinkList ListTailInsert(LinkList &L)
{
    InitList(L);      //初始化空表
    LNode *r = L, *s; //r为表尾指针
    int x;
    scanf("%d", &x);
    while (x != 9999)
    {
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        //在r结点之后插入元素x
        r = s;
        //r指向新的表尾结点
        //永远保持r指向最后一个结点
        scanf("%d", &x);
    }
    r->next = NULL; //尾结点指针置空
    return L;
}

//头插法逆向建立单链表
//头插法的重要应用:链表的逆置
LinkList ListHeadInsert(LinkList &L)
{
    InitList(L); //初始化空表
    LNode *s;
    int x;
    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;
}

//按位序删除(带头结点)
bool ListDelete(LinkList &L, int i, int &e)
{
    if (i < 1)
    {
        return false;
    }
    LNode *p = GetElem(L, i - 1); //找到第i-1个结点
    if (p == NULL)
    { //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;        //删除成功
}

//删除指定结点p
bool DeleteNode(LNode *p)
{
    if (p == NULL)
    {
        return false;
    }
    LNode *q = p->next;      //令q指向*p的后继结点
    p->data = p->next->data; //和后继结点交换数据域
    p->next = q->next;       //将*q结点从链中“断开”
    free(q);                 //释放后继结点的存储空间
    return true;
}

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

//打印函数(带头结点)
void print(LinkList &L)
{
    LNode *p = L->next;

    while (p != NULL)
    {
        if (p->next != NULL)
        {
            printf("%d->", p->data);
        }
        else
        {
            printf("%d", p->data);
        }
        p = p->next;
    }
    printf("\n");
}

int main()
{
    LinkList L; //声明一个指向单链表的指针

    InitList(L); //初始化一个空表

    if (Empty(L))
    {
        // ListInsert(L, 1, 1);
        // ListInsert(L, 2, 2);
        // ListInsert(L, 3, 3);
        // ListTailInsert(L);
        ListHeadInsert(L);
    }
    else
    {
        printf("failure!\n");
    }
    print(L);

    InsertPriorNode(L->next, 123);
    print(L);

    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = 555;
    InsertPriorNode(L->next, s);
    print(L);

    int e = 0;
    ListDelete(L, 1, e);
    print(L);
    printf("The deleted element is %d\n", e);

    DeleteNode(L->next);
    print(L);

    LNode *q = LocateElem(L, 2);
    if (q != NULL)
    {
        printf("Element 2 is in position %d\n", q->data);
    }
    else
    {
        printf("The element was not found!\n");
    }

    printf("Now the length is %d\n", Length(L));

    return 0;
}

input:

1
2
3
4
5
9999

output:

5->4->3->2->1
123->5->4->3->2->1
555->123->5->4->3->2->1
123->5->4->3->2->1
The deleted element is 555
5->4->3->2->1
Element 2 is in position 2
Now the length is 5

双链表

#include <bits/stdc++.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; //内存不足,分配失败
    }
    L->prior = NULL; //头结点的prior永远指向NULL
    L->next = NULL;  //头结点之后暂时还没有结点
    return true;
}

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

//在p结点之后插入q结点
bool InsertNextDNode(DNode *p, DNode *q)
{
    if (p == NULL || q == NULL)
    { //非法参数
        return false;
    }
    q->next = p->next; //将结点*q插入到结点*p之后
    if (p->next != NULL)
    { //如果p结点有后继结点
        p->next->prior = q;
    }
    q->prior = p;
    p->next = q;
    return true;
}

//删除p结点的后继结点
bool DeleteNextDNode(DNode *p)
{
    if (p == NULL)
    {
        return false;
    }
    DNode *q = p->next; //找到p的后继结点q
    if (q == NULL)
    { //p没有后继
        return false;
    }
    p->next = q->next;
    if (q->next != NULL)
    { //q结点不是最后一个结点
        q->next->prior = p;
    }
    free(q); //释放结点空间
    return true;
}

//循环释放各个数据结点
void DestoryList(DLinkList &L)
{
    while (L->next != NULL)
    {
        DeleteNextDNode(L);
    }
    free(L);  //释放头结点
    L = NULL; //头指针指向NULL
}

void print(DLinkList &L)
{
    DNode *p = L->next;
    while (p != NULL)
    {
        if (p->next != NULL)
        {
            printf("%d->", p->data);
        }
        else
        {
            printf("%d", p->data);
        }
        p = p->next;
    }
    printf("\n");
}

int main()
{
    DLinkList L; //声明一个指向双链表的指针

    InitDLinkList(L); //初始化双链表

    if (Empty(L))
    { //如果链表为空
        DNode *p, *q;
        int x;
        scanf("%d", &x);
        while (x != 9999)
        {
            p = L;
            q = (DNode *)malloc(sizeof(DNode));
            q->data = x;
            while (p->next != NULL)
            {
                p = p->next;
            }
            InsertNextDNode(p, q);
            scanf("%d", &x);
        }
        print(L);
        DeleteNextDNode(q->prior);
        print(L);
        DestoryList(L);
        if (L == NULL)
        {
            printf("empty!\n");
        }
        else
        {
            printf("failure!\n");
        }
    }
    else
    {
        printf("failure!\n");
    }

    return 0;
}

input:

1
2
3
4
5
9999

output:

1->2->3->4->5
1->2->3->4
empty!

循环单链表

#include <bits/stdc++.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;
    }
}

int main()
{
    LinkList L;

    InitList(L);

    if (Empty(L))
    {
        printf("success!\n");
    }
    else
    {
        printf("failure!\n");
    }

    //待补充

    return 0;
}

output:

success!

循环双链表

#include <bits/stdc++.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;
    }
    L->next = L; //头结点的prior指向头结点
    L->next = L; //头结点next指向头结点
    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;
    }
}

//在p结点之后插入q结点
bool InsertNextDNode(DNode *p, DNode *q)
{
    if (p == NULL || q == NULL)
    { //非法参数
        return false;
    }
    q->next = p->next; //将结点*q插入到结点*p之后
    p->next->prior = q;
    q->prior = p;
    p->next = q;
    return true;
}

//删除p结点的后继结点
bool DeleteNextDNode(DNode *p)
{
    if (p == NULL)
    {
        return false;
    }
    DNode *q = p->next; //找到p的后继结点q
    p->next = q->next;
    q->next->prior = p;
    free(q); //释放结点空间
    return true;
}

void print(DLinkList &L)
{
    DNode *p = L->next;
    while (p != L)
    {
        if (!isTail(L, p))
        {
            printf("%d->", p->data);
        }
        else
        {
            printf("%d", p->data);
        }
        p = p->next;
    }
    printf("\n");
}

int main()
{
    DLinkList L;

    InitDLinkList(L);

    if (Empty(L))
    { //如果链表为空
        DNode *p, *q;
        int x;
        scanf("%d", &x);
        while (x != 9999)
        {
            p = L;
            q = (DNode *)malloc(sizeof(DNode));
            q->data = x;
            while (!isTail(L, p))
            {
                p = p->next;
            }
            InsertNextDNode(p, q);
            scanf("%d", &x);
        }
        print(L);
        DeleteNextDNode(q->prior);
        print(L);
    }
    else
    {
        printf("failure!\n");
    }

    return 0;
}

input:

1
2
3
4
5
9999

output:

1->2->3->4->5
1->2->3->4

静态链表

#include <bits/stdc++.h>

#define MaxSize 10 //静态链表的最大长度

using namespace std;

//静态链表结构类型的定义1
struct Node
{
    int data; //存储数据元素
    int next; //下一个元素的数组下标
};

//静态链表结构类型的定义2
typedef struct
{
    int data; //存储数据元素
    int next; //下一个元素的数组下标
} SLinkList[MaxSize];

/*
typedef struct
{
    int data; //存储数据元素
    int next; //下一个元素的数组下标
}SLinkList[MaxSize];

↑
等价于
↓

struct Node
{
    int data; //存储数据元素
    int next; //下一个元素的数组下标
};
typedef struct Node SLinkList[MaxSize];

*/

/*

SLinkList a; //数组a作为静态链表

↑
等价于
↓

struct Node a[MaxSize]; //数组a作为静态链表

*/

int main()
{
    struct Node x;
    printf("sizeX=%d\n", sizeof(x));

    struct Node a[MaxSize];
    printf("sizeA=%d\n", sizeof(a));

    SLinkList b;
    printf("sizeB=%d\n", sizeof(b));

    return 0;
}

output:

sizeX=8
sizeA=80
sizeB=80

posted @ 2021-07-03 21:30  zhulu506  阅读(249)  评论(0编辑  收藏  举报