数据结构---链表

数据结构---链表,第1张

数据结构---链表

链表
  • 单向链表
    • 定义
    • 创建
      • 建链
      • 建表-头插法
      • 建表-尾插法
    • 遍历
      • 递归
      • 非递归
    • 求表长
    • 取第i个元素
    • 按值查找
    • 查p结点前驱
    • 查值为e的结点后继
    • 插入元素
    • 删除元素
    • 合并单链表
  • 循环链表
  • 双向链表
    • 定义
    • 插入
    • 删除

数据结构


单向链表 定义
typedef struct node {
     int data;
     struct node  *next;
}LNode, *linkList;

LNode   *h,*p;
//或者
linkList h,p;

头节点:第一个节点的前设节点,可有可无,也就是俗称的表头
头指针:指向(记录)链式存储中第1个节点位置(地址)的指针变量。

创建 建链
int InitList (linkList  &L)//带头节点
{
  L=new LNode ;
  if (L==NULL)
   {printf(“无内存空间可分配”);retutn 0;}
  L->next=NULL;
  return 1;
}
建表-头插法

void ListCreat1(linkList &L)
{ //用头插法建立带头结点的单链表
    LNode *p;
    L = new LNode;
    L->next = NULL;   //初始化一个空链表,L为头指针
    scanf(“% d”, &x); //x是和链表元素具有相同类型的变量,假设为整型
    while (x != flag) //flag为结束输入的标志,可自己设置如999
    {
        p = new LNode; //生成新结点
        p->data = x;   //输入元素值
        p->next = L->next;
        L->next = p;      //插入到表头
        scanf(“% d”, &x); //读入下一个元素的值
    }
}
建表-尾插法

linkList ListCreat2(linkList &L)
{ //用尾插法建立带头结点的单链表
    LNode *r, *p;
    L = new LNode;
    L->next = NULL;
    r = L;
    scanf(“% d”, &x);
    while (x != flag) //设置结束标志
    {
        p = new LNode;
        p->data = x; //赋值元素值
        r->next = p; //在尾部插入新结点
        r = p;       //r 指向新的尾结点
        scanf(“% d”, &x);
    }
    r->next = NULL; //最后结点的指针域放空指针
}
遍历 递归
void print(linkList L) //非递归
{
    linkList p = L->next;
    while (p)
    {
        printf(“% d”, p->data);
        p = p->next;
    }
}
非递归
void out(linkList p) //递归
{
    if (p)
    {
        printf(“% c”, p->data);
        out(p->next);
    }
}
求表长
int  ListLength(linkList  L)
{//求带头结点的单链表的长度
LNode *p; int j; 
p=L->next;      //p指向第一结点
 j=0;							
while(p!=NULL) 
 {
  j++;
  p=p->next;
 } //移动p指向下一结点
return  j;
} 
取第i个元素
linkList ListGet(linkList L, int i)
{ //在单链表L中查找第i个元素结点,返回该结点的地址,否则返回空
    LNode *p;
    int j;
    if (i < 1)
    {
        printf(“参数错误”);
        return NULL;
    }
    p = L->next;
    j = 1;
    while (p != NULL && j < i)
    {
        p = p->next;
        j++;
    }
    if (j == i)
        return p;
    else
        return NULL;
}
按值查找
linkList ListLocate1(linkList L, int x)
{ //在单链表L中查找值为x的结点,找到后返回其指针,否则返回空
    LNode *p;
    p = L->next;
    while (p != NULL && p->data != x)
        p = p->next;
    if (!p)
    {
        printf(“无值为X的结点”);
        return NULL;
    }
    else
        return p;
}
查p结点前驱
linkList ListLocate2(linkList L, LNode *p)
{ //在单链表L中求p指向的结点(假定存在)的前驱
    LNode *pre;
    if (L->next == p)
    {
        printf(“p指向第一元素结点,无前驱”);
        return NULL;
    }
    pre = L->next;
    while (pre != NULL && pre->next != p)
        pre = pre->next;
    if (pre)
        return pre;
    else
        return NULL;
}
查值为e的结点后继
linkList ListLocate3(linkList L, int e)
{ //在单链表L中求元素值为e的结点(假定存在)的后继
    LNode *p;
    p = L->next;
    while (p != NULL && p->data != e)
        p = p->next;
    if (p == NULL)
    {
        printf(“不存在值为e的结点”);
        return NULL;
    }
    else if (p->next == NULL)
    {
        printf(“值为e的结点是最后一个结点,无后继”);
        return NULL;
    }
    else
        return p->next;
}
插入元素

void ListInsert(linkList L, LNode *p, int x)
{//在结点p之前插入元素为x的结点
    LNode *pre;
    pre = L;
    while (pre->next != NULL && pre->next != p)
        pre = pre->next; //找p的直接前驱
    if (!pre->next)
    {
        printf(“不存在 * p结点”) ;return;
    }
    s = new Lnode; //创建新结点
    s->data = x;   //设置新结点的元素值
    s->next = pre->next;
    pre->next = s; //插入新结点
}
删除元素

void ListDel(linkList L, int i)
{ //删除单链表L上的第i个结点
    LNode *pre, *p;
    if (i < 1)
    {
        printf(“参数错误”);
        return;
    }
    if (i == 1)
    {
        p = L->next;
        L->next = p->next;
        free(p);
        return;
    }
    pre = L->next;
    j = 1;
    while (pre != NULL && j < i - 1)
    {
        pre = pre->next;
        j++;
    }
    if (pre == NULL)
    {
        printf(“删除位置不正确”);
        return;
    }
    p = pre->next;
    pre->next = p->next; //从链表中删除
    delete p;            //释放被删除结点
}
合并单链表
linkList Union(linkList la, linkList lb)
{
    //将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间
    linkList pa, pb, lc, pc;
    pa = la->next; //pa是链表la的工作指针
    pb = lb->next;     //pb是链表lb的工作指针
    lc = la;           //利用原a的表头做c的头
    pc = lc;           //pc是链表lc的工作指针
    while (pa && pb)   //la和lb均非空
    {
        if (pa->data <= pb->data)
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else
        {
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    //lb中元素插入lc
    }
    if (pa)
        pc->next = pa; //若pa未到尾,将pc指向pa
    else
        pc->next = pb; //若pb未到尾,将pc指向pb
}
循环链表

链表尾结点的指针域指向头结点

双向链表

如果希望查找前驱的时间复杂度达到O(1),我们可以用空间换时间,每个结点再加一个指向前驱的指针域,使链表可以进行双方向查找。用这种结点结构组成的链表称为双向链表

定义
typedef int ElemType;
typedef struct  DLNode
{ElemType data;           
 struct DLNode *prior,*next;
}DLNode,*DlinkList;
插入

删除

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5698855.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存