码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构——链表

时间:2019-01-01 14:59:02      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:col   false   eve   防止   get   指针的指针   inf   alt   main   

 

头指针或者尾指针需要改变,并且需要把改变的值带回到主程序,带回到调用处需要用的指针的指针;
当尾指针不发生改变,或者即使发生了改变也不希望带回到主程序当中就用指针;

1 链式存储结构

  特点:用一组任意的存储单元存储线性表中的数据元素;这组存储单元可以使连续的也可以是不连续的;每个数据元素除了存储数据外,还要存储前驱、后继元素的地址。

  每个元素包括数据域和指针域;存储数据的部分就是数据域,存储地址的部分就是指针域;

data address
数据域 指针域

 

 

 

2 单链表

  n个节点按链式存储结构存储,每个节点只包含一个指针域;

技术分享图片

技术分享图片

2.1 线性表的单链表存储结构

typedef int DataType;
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

2.2 获取指定位置的元素

typedef int DataType;
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

Node* getptr(Node* head,int pos)
{
   Node *p=head;
  if(p==NULL || pos==0)
  {
    return head;
  }
  for(int i=0;p&&i<pos;i++)
    p=p->next;
  return p;
}

void main()
{
  Node *head=NULL;
  ...
  Node *p=getptr(head,3); //获取第3个节点的元素
}

2.3 获取单链表中节点个数

typedef int DataType;
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

int getSize(Node* head)
{
  int size=0;
  Node *p=head;
  while(p)    //直到p指向的节点地址域为空时,停止循环,返回size
  {
    size++;
    p=p->next;
  }
  return size;
}

void main()
{
  Node *head=NULL;
  ...
  int len=getSize(head); //获取第3个节点的元素
}

技术分享图片

2.4 单链表插入节点

typedef int DataType;
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

bool insert(Node**head,int position,DataType d)
{
  if(position<0||position>getSize(*head))
    return false;
  Node *node=(Node*)malloc(sizeof(Node));
  node->next=NULL;
  node->next=d;
  if(position==0)   //if中的语句实现插入空链表或头部
  {
    node->next=*head;
    *head=node;
    return true;
  }
  Node *p=getptr(*head,position-1); //以下5条语句实现插入中间或者尾部
  Node *r=p->next;
  node->next=r;
  p->next=node;
  return true;
}

void main()
{
  Node *head=NULL;
  ...
  insert(&head,0,10); //头部或者空表插入数据10
  insert(&head,3,7); //第3个节点插入数据7
}

 

技术分享图片

2.5 单链表删除

bool erase(Node **head,int pos)
{
  if(pos<0 || pos>getSize(*head))
    return false;
  Node *p=*head;
  if(pos==0)
  {
    *head=(*head)->next;
    free(p);    //是否指针p,即删除p指向的节点
    p=NULL;  //节点不存在就让它为空,防止出现意外
    return true;
  }
  p=getptr(*head,pos-1);
  Node *q=p->next;
  p->next=q->next;
  free(q);
  q=NULL;

  return true;
}

void main()
{
  Node *head=NULL;
  insert(&head,0,10);
  insert(&head,0,8);
  insert(&head,0,3);
  insert(&head,0,5);
  erase(&head,0);
  erase(&head,1);
}

2.6 将两个线性链表合并

void union(Node *a,Node *b)
{
  Node *p=*a;
  if(p->next)
    p=p->next;
  p->next=b;
}

void main()
{
  Node *ahead=NULL;
  Node *bhead=NULL;
  insert(&ahead,0,10);
  insert(&ahead,0,3);
  insert(&ahead,0,8);
  insert(&ahead,0,5);
  insert(&bhead,0,7);
  insert(&bhead,0,6);
  insert(&bhead,0,2);
  insert(&bhead,0,4);
  union(ahead,bhead);
}

2.7 线性链表的倒置

void reverse(Node **head)
{
  Node *p=*head;
  Node *q=p->next;
  if(q==NULL)
    return;
  Node *r=q->next;
  if(p==*head) //可以不要,最好不要
    p->next=NULL;
  while(true)
  {
    q->next=p;
    if(r==NULL)
    {
      *head=q;
      break;
    }
    elase
    {
      p=q;
      q=r;
      r=r->next;
    }
  }
}

void main()
{
  Node *head=NULL;
  insert(&head,0,10);
  insert(&head,0,3);
  insert(&head,0,8);
  insert(&head,0,8);
  reverse(&head);
}

技术分享图片

技术分享图片

2.8 线性链表的遍历

void print(DataType d)
{
  printf("%d\n",d);
}

void trave(Node *head,void(*fun)(DataType))
{
  Node *p=head;
  while(p)
  {
    fun(p->data);
    p=p->next;
  }
}

void main()
{
  Node *head=NULL;
  insert(&head,0,10);
  insert(&head,0,3);
  insert(&head,0,8);
  insert(&head,0,8);
  trave(head,print);
}

3 单循环链表

循环链表:

  将单链表中最后一个节点的指针域由空改为指向第一个节点,使整个单链表形成一个环;

技术分享图片

3.1 线性表的单循环列表存储结构

typedef int DataType 
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

3.2 获取单循环链表中的节点个数

typedef int DataType 
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

int getSize(Node *rear)
{
  int size=0;
  if(rear)
  {
    Node *p=rear->next;
    while(p!=rear)
    {
      size++;
      p=p->next;
    }
    size++;
  }
  return size;
}

void main()
{
  Node *rear=NULL; //定义尾指针指向单链表最后一个节点,rear->next会指向头指针,相当于头指针
  ...
  int len=getSize(rear);
}

3.3 获取指定位置的元素

typedef int DataType 
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

Node *getptr(Node *rear,int pos)
{
  if(rear==NULL)
    return rear;
  if(pos<0 || pos>=getSize(rear))
    return NULL;
  Node *p=rear->next;
  for(int i=0;i<pos;i++)
    p=p->next;
  return p;
}

void main()
{
  Node *rear=NULL; 
  ...
  Node *p=getptr(rear,2);
}

3.4 单循环链表插入节点

typedef int DataType 
typedef struct Node
{
  DataType data;
  struct Node *next;
}Node;

bool insert(Node **rear,int position,DataType d)
{
  if(position<0 || position>getSize(*head))
    return false;
  Node *node=(Node*)malloc(sizeof(Node));
  node->data=d;
  node->next=NULL;
  if(position==0)
  {
    if(*rear==NULL)
    {
      node->next=node;
      *rear=node;
    }
    else
    {
      node->next=(*rear)->next;
      (*rear)->next=node;
    }
    return true;
  }
  Node *p=getptr(*head,position-1);
  Node *r=p->next;
  node->next-r;
  p->next=node;
  if(*rear=p)
  {
    *rear=node;
  }
  return ture;
}

void main()
{
  Node *rear=NULL;
  insert(&rear,0,10);
  insert(&rear,0,3);
  insert(&rear,0,8);
  insert(&rear,1,5);
}

3.5 单循环列表的删除

bool erase(Node **rear,int pos)
{
  if(*rear==NULL || pos<0 || pos>getSize(*head))
    return false;
  Node *p=(*rear)->next;
  if(pos==0)
  {
    (*rear)->next=p->next;
    free(p);    //是否指针p,即删除p指向的节点
    p=NULL;  //节点不存在就让它为空,防止出现意外
    return true;
  }
  p=getptr(*rear,pos-1);
  Node *q=p->next;
  p->next=q->next;
  if(q==*rear)
    *rear=p;
  free(q);
  q=NULL;

  return true;
}

void main()
{
  Node *rear=NULL;
  insert(&rear,0,10);
  insert(&rear,0,8);
  insert(&rear,0,3);
  insert(&rear,0,5);
  erase(&rear,0);
  erase(&rear,1);
}

 

数据结构——链表

标签:col   false   eve   防止   get   指针的指针   inf   alt   main   

原文地址:https://www.cnblogs.com/dongry/p/10025237.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!