数据结构---线性表的链式表示和实现

线性表的链式表示和实现

存储结构特点:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)

逻辑次序和物理次序不一定相同,对于数据元素来说,存储本身的信息还有后继的信息

访问时只能通过头指针进入链表,并通过每个结点的指针域向后顺序扫描其余结点

数据域:存储数据元素信息

指针域:存储直接后继存储位置的域,通常称作指针或链

单链表:

typedef struct LNode 

{

ElemType  data;

struct LNode *next; 

}LNode,*LinkList;// LinkList 为指向结构体 LNode 的指针类型

首元结点:存储第一个元素的结点

头结点:首元结点之前附设的结点,指针域指向首元结点

头指针:指向链表第一个结点的指针

顺序表---随机存储 链表---顺序存储

单链表基本操作实现

1.初始化---构造一个空表

(1)生成新结点作为头结点,用头指针L 指向头结点。
(2)头结点的指针域置空。

Status InitList(LinkList &L) 
{ 
L=new LNode; 
L->next=NULL; 
return OK;
}
2.取值

(1)用指针p指向首元结点,用j做计数器初值赋为1。

(2)从首元结点开始依次顺着链域next 向下访问,只要指向当前结点的指针 p 不为空(NULL), 并且没有到达序号为i的结点,则循环执行以下操作:

  • p指向下一个结点;
  • 计数器j相应加1;

(3)退出循环时, 如果指针p为空, 或者计数器j大于i, 说明指定的序号i值不合法(i大于表长n或i小于等于0), 取值失败返回ERROR; 否则取值成功, 此时j=i时,p所指的结点就是要找的第i个结点,用参数e保存当前结点的数据域, 返回OK。

Status GetElem(LinkList L,int i,ElemType &e)
{
p=L->next;
j=i;
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i)
return ERROR;
e=p->data;
return OK;
}
3.查找

(1)用指针p指向首元结点 。

(2)从首元结点开始依次顺着链域next向下查找, 只要指向当前结点的指针p不为空, 并且p所指结点的数据域不等于给定值e, 则循环执行以下操作: p指向下一个结点 。

(3)返回p。若查找成功,p此时即为结点的地址值,若查找失败,p的值即为NULL。

LNode *LocateELem(LinkList L,Elemtype e)
{
p=L->next;
while(p&&p->date!=e)
{
p=p->next;
}
return p;
}
4.插入

image-20220108163423280

(1)查找结点ai-1并由指针p指向该结点。

(2)生成一个新结点*s

(3)将新结点 的数据域置为 e。

(4)将新结点*s 的指针域指向结点ai

(5)将结点*p 的指针域指向新结点 *s。

Status Listinsert(LinkList &L,int i,ElemType e)
{
p=L;j=O; 
while (p && (j<i-1)) 
{p=p->next;++j;} 
if (!p I j>i- I 1) return ERROR; 
s=new LNode; 
s->data= e; 
s->next=p->next;
p->next=s;
return OK;
}
5.删除

(1)查找结点ai-1 并由指针p指向该结点。

(2)临时保存待删除结点ai的地址在q中 ,以备释放。

(3)将结点*p的指针域指向ai的直接后继结点。

(4)释放结点ai的空间。

Status ListDelete(LinkList &L,int i) 
{ 
while ((p->next) && (j<i-1)) 
{p=p->next; ++j;}
if (! (p->next) 11 (j>i-1)) return ERROR;
q=p->next;
p->next=q->next;
delete q;
return OK;
}
6.创建单链表---每个链表占用的空间不需预先分配划定,而是由系统按需即时生成。

从空表的初始状态起,依次建立各元素结点,并逐个插入链表。

1.前插法

前插法是通过将新结点逐个插入链表的头部(头结点之后)来创建链表,每次申请一个新结点,读入相应的数据元素值,然后将新结点插入到头结点之后。

(1)创建一个只有头结点的空链表。
(2)根据待创建链表包括的元素个数n, 循环n次执行以下操作:
• 生成一个新结点p;
• 输入元素值赋给新结点 * p的数据域;
• 将新结点
p插入到头结点之后。

image-20220108165629048

void CreateList_H(LinkList &L,int n) 
{
L=new LNode; 
L->next=NULL; 
for(i=O;i<n;++i)
{ 
p=new LNode; 
cin>>p->data; 
p->next=L->next;L->next=p;
}
}

2.后插法

后插法是通过将新结点逐个插入到链表的尾部来创建链表。 同前插法一样, 每次申请一个新结点, 读入相应的数据元素值。 不同的是, 为了使新结点能够插入到表尾, 需要增加一个尾指针r指向链表的尾结点。

(1)创建一个只有头结点的空链表。

(2)尾指针r初始化, 指向头结点。

(3)根据创建链表包括的元素个数n, 循环n次执行以下操作:

• 生成一个新结点* p;
• 输入元素值赋给新结点 * p 的数据域;
• 将新结点* p 插入到尾结点* r之后;
• 尾指针* r指向新的尾结点* p。
image-20220108170351613

void CreateList_R(LinkList &L,int n) 
{ 
L=new LNode; 
L->next=NULL;
r=L;
for(i=O;i<n;++i)
{
p=new LNode; 
cin>>p->data; 
p->next=NULL; r->next=p; 
r=p;
}
}

代码实现

#include<iostream>
using namespace std;
typedef struct LNode 
{
    int data;
    struct LNode* next;
}LNode, * LinkList;
bool InitList(LinkList& L);
void ShowList(LinkList L);
void CreateList(LinkList& L, int n);
void FoundList(LinkList L, int e);
void InsertList(LinkList& L, int i, int e);
void DeleteList(LinkList& L, int i);
int main()
{
    int n, e, a, b, c;
    LinkList L;
    InitList(L);
    cout << "请输入单链表长度:";
    cin >> n;
    CreateList(L, n);
    ShowList(L);
    cout << "请输入要查找的值:";
    cin >> e;
    FoundList(L, e);
    cout << "请输入要插入的位置:";
    cin >> a;
    cout << "请输入要插入的值:";
    cin >> b;
    InsertList(L, a, b);
    cout << "请输入要删除的位置:";
    cin >> c;
    DeleteList(L, c);
    return 0;
}
bool InitList(LinkList& L) 
{
    L = new LNode;
    L->next = NULL;
    return true;
}
void CreateList(LinkList& L, int n) {
    LinkList r, p;
    L = new LNode;
    L->next = NULL;
    r = L;
    cout << "请输入单链表:";
    for (int i = 0; i < n; i++) {
        p = new LNode;
        cin >> p->data;
        p->next = NULL;
        r->next = p;
        r = p;
    }
}
void ShowList(LinkList L) {
    LinkList p;
    p = L->next;
    cout << "单链表为:";
    while (p) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

void FoundList(LinkList L, int e) {
    LinkList p;
    p = L->next;
    int counts = 0;
    while (p) {
        if (p->data == e) {
            counts++;
            cout << "第" << counts << "次找到了与" << e << "相等的值" << endl;
        }
        p = p->next;
    }
    if (counts == 0) {
        cout << "没有找到与" << e << "相等的值" << endl;
    }
}
void InsertList(LinkList& L, int i, int e) {
    LinkList p, s;
    p = L;
    int counts = 0;
    while (p && (counts < i - 1)) {
        p = p->next;
        counts++;
    }
    s = new LNode;
    s->data = e;
    s->next = p->next;
    p->next = s;
    ShowList(L);
}
void DeleteList(LinkList& L, int i) {
    LinkList s;
    LinkList p = L;
    int counts = 0;
    while (p && (counts < i - 1)) {
        p = p->next;
        counts++;
    }
    s = p->next;
    p->next = s->next;
    delete s;
    ShowList(L);
}

posted on   眉目作山河  阅读(180)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示