数据结构:线性表

线性表

线性表(List):零个或多个数据元素的有限序列。

首先它是一个序列。也就是说,元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。

然后,线性表强调是有限的。

顺序表与单链表是线性表的两种最基本的存储结构,而静态链表是两者的完美结合,是系统进行动态存储分配的方法基础。线性表的这三种存储结构不但是其他数据结构(如树形结构、图型结构、集合等)存储方法的重要基础,同时本身也有广泛的应用。

线性表应该有以下基本的操作

  • InitList 初始化
  • ListEmpty 判空
  • ClearList 清空
  • GetElem 返回线性表第i个位置的元素
  • ListInsert 在线性表第i个位置插入元素
  • ListDelete 删除线性表的第i个位置的元素
  • ListLength *返回线性表的元素个数

顺序存储结构

可能有人第一次见线性表的顺序存储结构的时候,不禁怀疑:”这不就数组吗?这样定义好麻烦啊。有啥用啊?”

确实,在一些小体量的程序时,这样定义使用很麻烦,不如直接用数组。

但是这样封装起来后,程序就会很规范,虽然代码看上去很臃肿。

另外要实现的功能:

  • 对于已排好序的线性表,删除所有重复元素的算法。
  • 线性表”逆置”算法。
  • 线性表循环左移/右移 k 位的算法。
  • 合并两个已排好序的线性表的算法

下面是代码,结合注释理解

点击查看代码

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>

#define maxlenglth 1000
#define OK 1
#define ERROR 0

using namespace std;

typedef int Elemtype;
typedef int Status;
typedef int Position;

struct SeqList
{
    Elemtype data[maxlenglth];
    int lenth;
};// &#x7EBF;&#x6027;&#x8868;&#x7684;&#x5B9A;&#x4E49;

Status Display(SeqList L);//&#x6253; &#x5370;
SeqList InitList();// &#x521D;&#x59CB;&#x5316;
Position End(SeqList L); // &#x8FD4;&#x56DE;&#x6700;&#x540E;&#x7684;&#x4F4D;&#x7F6E;
Status Insert(Elemtype t, Position p, SeqList &L); // &#x5728;&#x4F4D;&#x7F6E;p&#x63D2;&#x5165;&#x5143;&#x7D20;t
Status Delete(Elemtype t, SeqList &L); //&#x5220;&#x9664;&#x6240;&#x6709;&#x5143;&#x7D20;t
Status Sort(SeqList &L); //&#x6392;&#x5E8F;
Status Unique(SeqList &L); //&#x5BF9;&#x6392;&#x5B8C;&#x5E8F;&#x53BB;&#x91CD;
Status ReverseList(SeqList &L); //&#x7FFB;&#x8F6C;&#xFF08;&#x9006;&#x7F6E;&#xFF09;
Status Merge(SeqList &L1, SeqList L2); //&#x5408;&#x5E76;&#x4E24;&#x4E2A;&#x6392;&#x597D;&#x5E8F;&#x7684;
Status Move(SeqList &L, int flag, int step); //&#x79FB;&#x52A8;

int main()
{
    // basic test
    int n1, n2;
    SeqList L1 = InitList();
    SeqList L2 = InitList();
    cout << "please input L1's lenth:"; cin >> n1;
    cout << "please input L1's data:" << "\n";
    for(int i = 1; i <= n1; i ++ ) { int x; cin>> x;
        Insert(x, L1.lenth + 1, L1);
    }
    Display(L1);
    cout << "----Delete----" << "\n";
    Elemtype temp;
    cin >> temp;
    Delete(temp, L1);
    Display(L1);

    cout << "----Sorted----" << "\n";
    Sort(L1);
    Display(L1);

    cout << "----Uniqued----" << "\n";
    Unique(L1);
    Display(L1);

    // merge test

    cout << "please input L2's lenth:"; cin >> n2;
    cout << "please input L2's data:" << "\n";
    for(int i = 1; i <= n2; i ++ ) { int x; cin>> x;
        Insert(x, L2.lenth + 1, L2);
    }
    Display(L2);
    cout << "----Merged----" << "\n";
    Merge(L1, L2);
    Display(L1);

    // move test
    int flag, step;
    cout << "left(1) right(0):"; cin >> flag;
    cout << "move step:"; cin >> step;
    Move(L1, flag, step);
    Display(L1);

    cin >> n1;

    return 0;
}

Status Display(SeqList L)
{
    for(int i = 1; i <= 1="=" l.lenth; i ++ ) cout << l.data[i] " \n"[i="=" l.lenth]; } seqlist initlist() { list; list.lenth="0;" return position end(seqlist l) status insert(elemtype t, p, &l) if(l.lenth + maxlenglth) "full list!" "\n"; 1; if(p> L.lenth + 1 || p < 1)
    {
        cout << "Invalid Position!" << "\n";
        return 1;
    }
    L.lenth += 1;
    for(int i = L.lenth; i > p; i -- )
    {
        L.data[i] = L.data[i - 1];
    }
    L.data[p] = t;
    return 0;
}

Status Delete(Elemtype t, SeqList &L)
{
    Position idx = 0;
    for(int i = 1; i <= 1 l.lenth; i ++ ) { if(l.data[i] !="t)" idx ++; l.data[idx]="L.data[i];" } l.lenth="idx;" return 0; status sort(seqlist &l) sort(l.data + 1, l.data 1); unique(seqlist position elemtype last="0;" for(int <="L.lenth;" ++) if(i="=" 1) }else if(last reverselist(seqlist j="L.lenth;" j; ++, -- swap(l.data[i], l.data[j]); merge(seqlist &l1, seqlist l2) if(l1.lenth l2.lenth>= maxlenglth)
    {
        cout << "Overflow!" << "\n";
        return 1;
    }
    for(int i = L2.lenth + 1, j = 1; j <= l1.lenth; j ++ , i ++) { l2.data[i]="L1.data[j];" } position idx="0;" i, j; for(i="1," + 1; <="L2.lenth" && l2.lenth;) if(l2.data[i] ++; l1.data[idx]="L2.data[i];" }else while(i while(j l1.lenth) l1.lenth return 0; status move(seqlist &l, int flag, step) static seqlist temp="InitList();" temp.lenth="L.lenth;" if(temp.lenth="=" 0) for(int ) temp.data[i]="L.data[i];" step="step" % l.lenth; if(flag="=" flag="1;" * step; if(j> temp.lenth)
        {
            j -= temp.lenth;
        }
        if(j < 1)
        {
            j += temp.lenth;
        }

        L.data[j] = temp.data[i];
    }
    return 0;
}
</=></=></=></=></=></cstring></iostream></algorithm></cstdio>

链式存储结构

关于链表,有三种经典类型: 单链表双向链表循环链表

而每种类型又有很多考法

但其核心都是 指针域的用法

另外要实现的功能:

  • 对于已排好序的线性表,删除所有重复元素的算法。
  • 线性表”逆置”算法。
  • 线性表循环左移/右移 k 位的算法。
  • 合并两个已排好序的线性表的算法

点击查看代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>

#define OK 0
#define ERROR 1

using namespace std;

typedef int Elemtype;
typedef int Status;

struct Node{

    Elemtype data;
    Node * next;
};//&#x94FE;&#x8868;&#x5B9A;&#x4E49;

typedef Node * Position;
typedef Node * LIST;

void Creat(LIST head,int size);//&#x521B;&#x5EFA;
void ForwardInsert(LIST head,Elemtype x);//&#x5934;&#x63D2;
void BackInsert(LIST head,int x);//&#x5C3E;&#x63D2;
void Travel(LIST head);//&#x904D;&#x5386;
Status IsEmpty(LIST head);//&#x5224;&#x7A7A;
void AllDelete(LIST head);//&#x5220;&#x9664;
void SomeDataDelete(LIST head,Elemtype x);//&#x5220;&#x9664;&#x4E00;&#x4E2A;&#x6570;
void SomeDataInsert(LIST head,Elemtype x,int num);//&#x5728;&#x67D0;&#x4F4D;&#x7F6E;&#x63D2;&#x5165;&#x4E00;&#x4E2A;&#x6570;
void Sort(LIST head, int (*cmp)(Elemtype, Elemtype));//&#x5192;&#x6CE1;&#x6392;&#x5E8F;
int Ascend(Elemtype x, Elemtype y);//&#x5347;&#x5E8F;
int Descend(Elemtype x, Elemtype y);//&#x964D;&#x5E8F;
Position Locate(Elemtype x, LIST head);
void Unique(LIST head);//&#x53BB;&#x91CD;
Status Reverse(LIST head);//&#x7FFB;&#x8F6C;
Status Move(LIST head, int flag, int step);//&#x5FAA;&#x73AF;&#x79FB;&#x52A8;
Status Merge(LIST head1, LIST head2);//&#x5408;&#x5E76;&#x4E24;&#x4E2A;&#x6392;&#x597D;&#x5E8F;&#x7684;&#x94FE;&#x8868;
int Len(LIST head);//&#x6C42;&#x94FE;&#x8868;&#x957F;
void MergeTest();//&#x5408;&#x5E76;&#x7684;&#x6D4B;&#x8BD5;

int main()
{
    LIST head = (LIST)malloc(sizeof(Node));//&#x5934;&#x8282;&#x70B9;
    head->next = NULL;

    int num, i;
    Elemtype temp;

    cout << "list num:";
    cin >> num;
    Creat(head,num);
    Travel(head);

    cout << "Insert forwarddata:";//&#x5934;&#x63D2;
    cin >> temp;
    ForwardInsert(head,temp);
    Travel(head);

    cout << "Insert backdata:";//&#x5C3E;&#x63D2;
    cin >> temp;
    BackInsert(head,temp);
    Travel(head);

    cout << "Somedata delete:";//&#x5220;&#x9664;
    cin >> temp;
    SomeDataDelete(head,temp);
    Travel(head);

    cout << "SomeDataInsert:(data and which):"; //&#x67D0;&#x4E00;&#x4F4D;&#x7F6E;&#x63D2;&#x5165;&#x67D0;&#x4E2A;&#x6570;&#xFF08;BUG&#x4E0D;&#x53EF;&#x5C3E;&#x63D2;&#xFF09;
    cin >> temp >> i;
    SomeDataInsert(head,temp,i);
    Travel(head);

    // &#x6392;&#x5E8F;&#x6D4B;&#x8BD5;
    cout << "----Sorted----" << "\n";
    Sort(head,Descend);
    Travel(head);

    //&#x53BB;&#x91CD;&#x6D4B;&#x8BD5;
    cout << "----Uniqued----" << "\n";
    Unique(head);
    Travel(head);

    // &#x7FFB;&#x8F6C;&#x6D4B;&#x8BD5;
    cout << "----Reversed----" << "\n";
    Reverse(head);
    Travel(head);

    // &#x5FAA;&#x73AF;&#x5DE6;(&#x53F3;)&#x79FB;&#x6D4B;&#x8BD5;
    cout << "----Move----" << "\n";
    int flag ,step;
    cout << "(right, left)(0,1)---(step)" << "\n";
    cin >> flag >> step;
    Move(head, flag, step);
    Travel(head);

    // &#x5408;&#x5E76;&#x6D4B;&#x8BD5;

    MergeTest();

    AllDelete(head);
    Travel(head);
    free(head);//free&#x6389;&#x5934;&#x8282;&#x70B9;

    return 0;
}

void MergeTest()
{
    int num;

    cout << "----Merge----" << "\n";
    LIST h1 = (LIST)malloc(sizeof(Node));
    h1->next = NULL;
    cout << "list1 num:";cin >> num;
    Creat(h1,num);
    Sort(h1, Descend);

    LIST h2 = (LIST)malloc(sizeof(Node));
    h2->next = NULL;
    cout << "list2 num:";cin >> num;
    Creat(h2,num);
    Sort(h2, Descend);

    Merge(h1, h2);
    cout << "Merged list:" << "\n";
    Travel(h1);
    AllDelete(h1);
    free(h1);
    free(h2);
}

Status Merge(LIST head1, LIST head2)
{
    LIST p1 = head1->next, p2 = head2->next;
    LIST temp = head1;
    while(p1 != NULL && p2 != NULL)
    {
        if(p1->data < p2->data)
        {
            temp->next = p1;
            p1 = p1->next;
        }else
        {
            temp->next = p2;
            p2 = p2->next;
        }
        temp = temp->next;
    }
    while(p1 != NULL)
    {
        temp->next = p1;
        p1 = p1->next;
        temp = temp->next;
    }

    while(p2 != NULL)
    {
        temp->next = p2;
        p2 = p2->next;
        temp = temp->next;
    }

    temp->next = NULL;
    return OK;
}

Status Move(LIST head, int flag, int step)
{
    int len = Len(head);
    step = step % len;
    if(step == 0)
    {
        return OK;
    }
    if(flag == 0)
    {
        step = len - step;
    }

    LIST p, q, s;
    p = q = s = head;

    p = p->next;

    int idx = 0;
    while(s->next != NULL)
    {
        idx ++;
        s = s->next;
        if(idx == step)
        {
            q = s;
        }
    }

    head->next = q->next;
    s->next = p;
    q->next = NULL;

    return OK;
}
int Len(LIST head)
{
    LIST p = head;
    int cnt = 0;
    while(p->next != NULL)
    {
        cnt ++;
        p = p->next;
    }
    return cnt;
}

void Unique(LIST head)
{
    Elemtype last;
    LIST p, q;
    p = head->next;
    if(p == NULL || p->next == NULL)
    {
        return;
    }
    last = p->data;
    q = p->next;
    while(q != NULL)
    {
        if(q->data == last)
        {
            p->next = q->next;
            free(q);
            if(p->next == NULL)
            {
                q = NULL;
            }else
            {
                q = p->next;
            }
        }else
        {
            last = q->data;
            q = q->next;
            p = p->next;
        }
    }
}
Status Reverse(LIST head)
{
    LIST p, q, s;
    p = q = s = head->next;
    q = p->next;

    while(q != NULL)
    {
        p->next = q->next;
        q->next = s;
        s = q;
        q = p->next;
    }
    head->next = s;
    return OK;
}

Position Locate(Elemtype x, LIST head)
{
    Position p = head;
    while(p->next != NULL)
    {
        if(p->data == x)
        {
            return p;
        }else
        {
            p = p->next;
        }
    }
    return p;/* &#x5982;&#x679C;&#x6CA1;&#x6709;&#x627E;&#x5230; */
}

int Descend(Elemtype x, Elemtype y)
{
    return x > y;
}
int Ascend(Elemtype x, Elemtype y)
{
    return x < y;
}
void Sort(LIST head, int(*cmp)(Elemtype, Elemtype))
{
    if(head->next == NULL)
    {
        cout << "Empty Node!\n";
        return;
    }
    if(head->next->next==NULL)
    {
        cout << "Only one element!\n";
        return;
    }
    LIST p1;
    LIST p2;
    for (p1 = head->next; p1->next != NULL; p1 = p1->next)
    {
         for (p2 = p1->next; p2!=NULL; p2 = p2->next)
         {
            if ((*cmp)(p1->data, p2->data))
            {
                swap(p1->data, p2->data);
            }
        }
    }
}
void Creat(LIST head, int size)
{
    LIST p = head;
    for(int i = 1;i <= size; i ++) { list newnode="(LIST)malloc(sizeof(Node));" newnode->next = NULL;
        cin >> newnode->data;
        p->next = newnode;
        p = newnode;
    }
}
void ForwardInsert(LIST head, Elemtype x)
{
    LIST newhead = (LIST)malloc(sizeof(Node));
    newhead->data = x;
    newhead->next = head->next;
    head->next = newhead;
    return;
}
void Travel(LIST head)
{
    LIST p = head;
    while(p->next != NULL)
    {
        p = p->next;
        cout << p->data << " ";
    }
    cout << "\n";
    return;
}
void BackInsert(LIST head, Elemtype x)
{
    LIST p = head;
    LIST back = (Node*)malloc(sizeof(Node));
    back->next = NULL;
    back->data = x;
    while(p->next != NULL)
    {
        p = p->next;
    }
    p->next = back;
    return;
}
Status IsEmpty(LIST head)
{
    if(head->next == NULL)
    {
        cout << "is Empty!" << "\n";
        return OK;
    }else
    {
        cout << "not Empty!" << "\n";
        return ERROR;
    }
}
void AllDelete(LIST head)
{
    LIST p = head->next;
    LIST temp = head;
    while(p != NULL)
    {
        temp = p;
        p = p->next;
        free(temp);
    }
    head->next = NULL;
    return;
}
void SomeDataDelete(LIST head, Elemtype x)
{
    LIST p = head->next;
    LIST last = head;
    LIST temp = NULL;
    while(p != NULL)
    {
        if(temp != NULL)
        {
            free(temp);

            temp = NULL;
        }
        if(p->data == x)
        {
            last->next = p->next;
            temp = p;
        }else
        {
            last = last->next;
        }
        p = p->next;
    }
    return;
}
void SomeDataInsert(LIST head,Elemtype x,int num)
{
    LIST p = head;
    LIST last = head;
    int idx = 0;
    while(p->next != NULL)
    {
        p = p->next;
        idx ++;
        if(idx == num)
        {
            LIST NewNode = (LIST)malloc(sizeof(Node));
            NewNode->data = x;
            last->next = NewNode;
            NewNode->next = p;
        }
        last = last->next;
    }
}
</=></cstdlib></algorithm></cstdio></cstring></iostream>

静态链表

静态链表其实就是将 指针域游标来代替 指针

游标: Cursor

所有它的大小也取决于最先开始建立的数组大小。

这里插入一张《大话数据结构》的图片

数据结构:线性表

实现基本功能和逆置的静态链表:

点击查看代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

#define OK 1
#define ERROR 0

#define MAXSIZE 1000

using namespace std;

typedef int Status;
typedef int ElemType;

typedef struct
{
    ElemType data;
    int cur;  /* &#x6E38;&#x6807;(Cursor) &#xFF0C;&#x4E3A;0&#x65F6;&#x8868;&#x793A;&#x65E0;&#x6307;&#x5411; */
} Component,StaticLinkList[MAXSIZE];

/* &#x5C06;&#x4E00;&#x7EF4;&#x6570;&#x7EC4;space&#x4E2D;&#x5404;&#x5206;&#x91CF;&#x94FE;&#x6210;&#x4E00;&#x4E2A;&#x5907;&#x7528;&#x94FE;&#x8868;&#xFF0C;space[0].cur&#x4E3A;&#x5934;&#x6307;&#x9488;&#xFF0C;"0"&#x8868;&#x793A;&#x7A7A;&#x6307;&#x9488; */
Status InitList(StaticLinkList space)
{
    for(int i = 0; i < MAXSIZE - 1; i ++ )
        space[i].cur = i + 1;
    space[MAXSIZE - 1].cur = 0; /* &#x76EE;&#x524D;&#x9759;&#x6001;&#x94FE;&#x8868;&#x4E3A;&#x7A7A;&#xFF0C;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x7684;cur&#x4E3A;0 */
    return OK;
}

/* &#x82E5;&#x5907;&#x7528;&#x7A7A;&#x95F4;&#x94FE;&#x8868;&#x975E;&#x7A7A;&#xFF0C;&#x5219;&#x8FD4;&#x56DE;&#x5206;&#x914D;&#x7684;&#x7ED3;&#x70B9;&#x4E0B;&#x6807;&#xFF0C;&#x5426;&#x5219;&#x8FD4;&#x56DE;0 */
int Malloc_SSL(StaticLinkList space)
{
    int i = space[0].cur;                   /* &#x5F53;&#x524D;&#x6570;&#x7EC4;&#x7B2C;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x7684;cur&#x5B58;&#x7684;&#x503C; */
                                            /* &#x5C31;&#x662F;&#x8981;&#x8FD4;&#x56DE;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x5907;&#x7528;&#x7A7A;&#x95F2;&#x7684;&#x4E0B;&#x6807; */
    if (space[0]. cur)
        space[0]. cur = space[i].cur;       /* &#x7531;&#x4E8E;&#x8981;&#x62FF;&#x51FA;&#x4E00;&#x4E2A;&#x5206;&#x91CF;&#x6765;&#x4F7F;&#x7528;&#x4E86;&#xFF0C; */
                                            /* &#x6240;&#x4EE5;&#x6211;&#x4EEC;&#x5C31;&#x5F97;&#x628A;&#x5B83;&#x7684;&#x4E0B;&#x4E00;&#x4E2A; */
                                            /* &#x5206;&#x91CF;&#x7528;&#x6765;&#x505A;&#x5907;&#x7528; */
    return i;
}

/*  &#x5C06;&#x4E0B;&#x6807;&#x4E3A;k&#x7684;&#x7A7A;&#x95F2;&#x7ED3;&#x70B9;&#x56DE;&#x6536;&#x5230;&#x5907;&#x7528;&#x94FE;&#x8868; */
void Free_SSL(StaticLinkList space, int k)
{
    space[k].cur = space[0].cur;    /* &#x628A;&#x7B2C;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x7684;cur&#x503C;&#x8D4B;&#x7ED9;&#x8981;&#x5220;&#x9664;&#x7684;&#x5206;&#x91CF;cur */
    space[0].cur = k;               /* &#x628A;&#x8981;&#x5220;&#x9664;&#x7684;&#x5206;&#x91CF;&#x4E0B;&#x6807;&#x8D4B;&#x503C;&#x7ED9;&#x7B2C;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x7684;cur */
}

/* &#x521D;&#x59CB;&#x6761;&#x4EF6;&#xFF1A;&#x9759;&#x6001;&#x94FE;&#x8868;L&#x5DF2;&#x5B58;&#x5728;&#x3002;&#x64CD;&#x4F5C;&#x7ED3;&#x679C;&#xFF1A;&#x8FD4;&#x56DE;L&#x4E2D;&#x6570;&#x636E;&#x5143;&#x7D20;&#x4E2A;&#x6570; */
int ListLength(StaticLinkList L)
{
    int j = 0;
    int i = L[MAXSIZE-1].cur;
    while(i)
    {
        i = L[i].cur;
        j ++;
    }
    return j;
}

/*  &#x5728;L&#x4E2D;&#x7B2C;i&#x4E2A;&#x5143;&#x7D20;&#x4E4B;&#x524D;&#x63D2;&#x5165;&#x65B0;&#x7684;&#x6570;&#x636E;&#x5143;&#x7D20;e   */
Status ListInsert(StaticLinkList L, int i, ElemType e)
{
    int j, k, l;
    k = MAXSIZE - 1;   /* &#x6CE8;&#x610F;k&#x9996;&#x5148;&#x662F;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x7684;&#x4E0B;&#x6807; */
    if (i < 1 || i > ListLength(L) + 1)
        return ERROR;
    j = Malloc_SSL(L);   /* &#x83B7;&#x5F97;&#x7A7A;&#x95F2;&#x5206;&#x91CF;&#x7684;&#x4E0B;&#x6807; */
    if (j)
    {
        L[j].data = e;   /* &#x5C06;&#x6570;&#x636E;&#x8D4B;&#x503C;&#x7ED9;&#x6B64;&#x5206;&#x91CF;&#x7684;data */
        for(l = 1; l <= 1 i - 1; l++) * 找到第i个元素之前的位置 k="L[k].cur;" l[j].cur="L[k].cur;" 把第i个元素之前的cur赋值给新元素的cur l[k].cur="j;" 把新元素的下标赋值给第i个元素之前元素的ur return ok; } error; 删除在l中第i个数据元素 status listdelete(staticlinklist l, int i) { j, k; if (i < ||> ListLength(L))
        return ERROR;
    k = MAXSIZE - 1;
    for (j = 1; j <= i - 1; j++) k="L[k].cur;" j="L[k].cur;" l[k].cur="L[j].cur;" free_ssl(l, j); return ok; } status listtraverse(staticlinklist l) { int while(i) cout << l[i].data " "; j++; "\n"; reverse(staticlinklist k; l[i].cur="j;" l[maxsize-1].cur="j;" main() staticlinklist l; i; "--- creat ---" "num: n;cin>> n;
    for(int i = 1; i <= n ; i ++ ) { int e; cin>> e;
        ListInsert(L, i, e);
    }
    ListTraverse(L);
    cout << "--- Reverse ---" << "\n";
    Reverse(L);
    ListTraverse(L);

    return 0;
}

</=></=></=></algorithm></cstdio></cstring></iostream>

说到静态链表,就不得不说它的一个应用: 邻接表

邻接表可以用作图的存储,可以存储有向图或无向图

  • idx 游标,可认为是第 idx的意思
  • h[N] 有N个顶点,每个点都可能会连有边, h[i]存储 顶点i的所有出边指向的点的 集合
  • e[N] 存储该节点的出边指向的顶点
  • ne[N] 存储该节点的下一个节点的 游标
  • w[N] 存储该节点代表的边的权重
int h[N], e[N], ne[N], idx;

// &#x6DFB;&#x52A0;&#x4E00;&#x6761;&#x8FB9;a->b
void add(int a, int b) //a&#x5230;b&#x6DFB;&#x52A0;&#x4E00;&#x6761;&#x8FB9; &#x4E8B;&#x5B9E;&#x4E0A;&#x662F; &#x5934;&#x63D2;&#x6CD5;
{
    e[idx] = b;//&#x8282;&#x70B9;idx&#x5B58;&#x50A8;&#x9876;&#x70B9;b
    ne[idx] = h[a];//&#x5C06;&#x8282;&#x70B9;idx&#x6307;&#x5411;&#x7684;&#x8282;&#x70B9; &#x6307;&#x5411; a&#x9876;&#x70B9;&#x6240;&#x6307;&#x5411;&#x7684;&#x8282;&#x70B9;&#xFF08;&#x5934;&#x8282;&#x70B9;&#xFF09;
    h[a] = idx ++ ; //&#x5C06;&#x5934;&#x6307;&#x9488;&#x7684;&#x6307;&#x5411;&#x4E3A;&#x65B0;&#x7684;&#x5934;&#x8282;&#x70B9;
}

// &#x521D;&#x59CB;&#x5316;
idx = 0;
memset(h, -1, sizeof h); //&#x521D;&#x59CB;&#x5316; &#x6240;&#x6709;&#x7684;&#x5934;&#x6307;&#x9488;&#x6307;&#x5411;-1
//&#x8FD9;&#x6837;&#x5F53;&#x904D;&#x5386;&#x7684;&#x65F6;&#x4FAF;,&#x56E0;&#x4E3A;&#x6E38;&#x6807;&#x4E0D;&#x53EF;&#x80FD;&#x51FA;&#x73B0;-1&#xFF0C;&#x5C31;&#x53EF;&#x4EE5;&#x5F53;&#x4F5C;&#x904D;&#x5386;&#x7EC8;&#x6B62;&#x6761;&#x4EF6;

参考文献

  • 程杰. 大话数据结构:溢彩加强版[M]. 北京: 清华大学出版社, 2020.

Original: https://www.cnblogs.com/Az1r/p/16720710.html
Author: 江水为竭
Title: 数据结构:线性表

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/685959/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球