数据结构--链表(代码实现)

链表分类

链表分为单向链表(Singly linked lis)、双向链表(Doubly linked list)、循环链表(Circular Linked list)。

 

应用:  1).用于数据数目事先无法确定的情况;
             2).用于数据数在内存中不连续存放的情况;
       组成:   1). 头指针
                     2). 结点(节点)
             2.1  数据域
             2.2  指针域(指向下一个节点)
 2.链表操作:
      2.1 链表创建:
          步骤:1.创建一个结点(申请可以存放一个结点数据的内存空间)
            2.填充结点数据(实际数据,指针)
        3.返回头结点首地址

3 链表插入:
          步骤:1.创建一个结点(申请可以存放一个结点数据的内存空间)
            2.填充结点数据(实际数据,指针)
        3.根据插入算法,将结点链接到链表中。

4 链表删除

单向链表(Singly linked lis)

单向链表是最简单的链表形式。我们将链表中最基本的数据称为节点(node),每一个节点包含了数据块和指向下一个节点的指针。

#ifndef __LIST_H__
#define __LIST_H__

typedef int DATA;

typedef struct node
{
  DATA data;
  struct node* next;
}Node;

Node* list_create(DATA);
Node* list_addhead(Node*,DATA);
Node* list_addtail(Node*,DATA);
Node* list_addtail_v2(Node*,DATA);
Node* list_delete(Node*,DATA);
void list_show(Node*);
void list_free(Node**);




#endif

#include "list.h"
#include <stdlib.h>
#include <stdio.h>

Node* list_create(DATA data)
{
   Node* p = (Node*)malloc(sizeof(Node));
   if(!p)
   {
      puts("申请内存失败!");
      return NULL;
   }
   p->data = data;
   p->next = NULL;

   return p;
}

Node* list_addhead(Node* head,DATA data)
{
  if(!head)
  {
     return list_create(data);
  }
  
   Node* p = (Node*)malloc(sizeof(Node));
   if(!p)
   {
      puts("申请内存失败!");
      return NULL;
   }
   p->data = data;
   p->next = head;

   head = p;

   return head;
}

Node* list_addtail(Node* head,DATA data)
{
   if(!head)
      return list_create(data);

   Node* p = (Node*)malloc(sizeof(Node));
   if(!p)
   {
      puts("申请内存失败!");
      return head;
   }
   p -> data = data;
   p -> next = NULL;
  
   Node* q = head;
   while(q->next)
   {
      q = q->next;
   }
   q ->next = p;
   return head;
}

Node* list_addtail_v2(Node* head,DATA data)
{
   Node* pNew = (Node*)malloc(sizeof(Node));
   if(!pNew)
   {
      puts("申请内存失败!");
      return head;
   } 
   pNew -> data = data;
   pNew -> next = NULL;

   Node* p = head,*q = NULL;
   while(p)
   {
       q = p;
       p = p ->next;
   }
   if(head)
      q->next = pNew;
   else
      head = pNew;

   return head;
}

Node* list_delete(Node* head,DATA del)
{
   if(!head)
   {
     puts("链表为空!!!");
     return NULL;
   }
   Node* p = head;
   if(head -> data == del)
   {
      head = head->next;
      free(p);
      return head; 
   }
   Node* q = NULL;
   
   while(p)
   {
     if(p -> data == del)
     {
        q->next = p ->next;
        free(p);
        return head;
     }
      q = p;
      p = p->next;
   }
   puts("删除的数据不存在!");
   return head;
}
void list_show(Node* head)
{
   Node* p = head;
   while(p)
   {
      printf("%5d",p->data);
      p = p->next;
   }
   printf("\n");
}
void list_free(Node** head)
{
   Node *p = *head,*q;
  
   while(p)
   {
      q = p;
      p = p->next;
      free(q);
   }
   *head = NULL;
}
#include "list.h"
#include <stdio.h>


int main(void)
{
  int del;
  int a[] = {1,3,5,7,9};
  Node* head = NULL;
  
  head = list_delete(head,7);
  
  register int i = 0;

  for(; i< sizeof a /sizeof a[0]; i++)
  {
      head = list_addtail_v2(head,a[i]);
  }
  list_show(head);
  puts("=============");

  while(1)
  {
     puts("请输入要删除的数据:");
     scanf("%d",&del);
     if(del == -1)
       break;
     head = list_delete(head,del);
          
     list_show(head);
  }

  list_free(&head);
  
  list_show(head);

  return 0;
}

双向链表(Doubly linked list)


顾名思义,双向链表就是有两个方向的链表。同单向链表不同,在双向链表中每一个节点不仅存储指向下一个节点的指针,而且存储指向前一个节点的指针。通过这种方式,能够通过在O(1)时间内通过目的节点直接找到前驱节点,但是同时会增加大量的指针存储空间。

#ifndef __DLIST_H__
#define __DLIST_H__

typedef int DATA;

typedef struct _node
{
  DATA data;
  struct _node *prev;
  struct _node *next;
}Node;

int Dlist_create(Node** head,DATA data);
int Dlist_addhead(Node** head,DATA data);
int Dlist_addtail(Node** head,DATA data);
int Dlist_insert_bypos(Node** head,Node* pos,DATA data);
int Dlist_insert(Node** head,DATA data1,DATA data);

Node* Dlist_find(Node*,DATA);

int Dlist_delete_bypos(Node** head,Node* pos);
int Dlist_delete(Node** head,DATA data);

void Dlist_show(Node*);
void Dlist_free(Node** head);

#endif
#include "Dlist.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/**
  * @brief  创建双向链表
  * @param  head: 头指针地址
  * @param  data: 节点数据
  * @retval 成功返回0,失败返回-1
  */
int Dlist_create(Node** head,DATA data)
{
  Node* p = (Node*)malloc(sizeof(Node));

  if(!p)
  {
    puts("创建结点失败!");
    return -1;
  }

  p -> data = data;
  p -> next = NULL;
  p -> prev = NULL;
  *head = p;

  return 0;
}

int Dlist_addhead(Node** head,DATA data)
{
   Node* p = (void*)malloc(sizeof(Node));
   if(!p)
   {
       puts("创建结点失败\n");
       return -1;
   }
   p -> data = data;
   p -> prev = NULL;
   p -> next = *head;

   if(*head)
       (*head)->prev = p;
   *head = p;
   
   return 0;
}


int Dlist_addtail(Node** head,DATA data)
{
   Node* p  = *head,*q = NULL;

   Node* pNew = (void*)malloc(sizeof(Node));
   if(!pNew)
   {
       puts("创建结点失败\n");
       return -1;
   }
   pNew -> data = data;
   pNew -> next = NULL;

   while(p)
   {
      q = p;
      p = p -> next;
   }
   
   pNew -> prev = q;
   if(*head)
       q -> next = pNew;
   else
       *head = pNew;
   return 0;
}

Node* Dlist_find(Node* head,DATA data)
{
  Node* p = head;
  while(p)
  {
     if(p -> data == data)
        return p;
     p = p -> next;
  }
  return NULL;
}

int Dlist_insert_bypos(Node** head,Node* pos,DATA data)
{
   if(*head == NULL)
     return Dlist_create(head,data);
   if(*head == pos)
     return Dlist_addhead(head,data);
   if(!pos)
     return Dlist_addtail(head,data);

   Node* p = (Node*)malloc(sizeof(Node));
   if(!p)
   {
      puts("创建结点失败!");
      return -1;
   }
   p -> data = data;
   p -> prev = pos -> prev;
   p -> next = pos;

   pos -> prev -> next = p;
   pos -> prev = p;

   return 0;
}

int Dlist_insert(Node** head,DATA data1,DATA data2)
{
  Node* pos = Dlist_find(*head,data1);
  return Dlist_insert_bypos(head,pos,data2); 
}

int Dlist_delete_bypos(Node** head,Node* pos)
{
   if((*head == NULL) || !pos)
   {
     puts("链表为空,或位置不存在!");
     return -1;
   } 
   if((pos->prev == NULL) &&(pos->next == NULL))
   {
      *head = NULL;
      free(pos);
      return 0;
   }
   if(pos == *head)
   {
      pos->next->prev = NULL;
      *head = pos->next;
      free(pos);
      return 0;
   }
   if(pos -> next == NULL)
   {
      pos -> prev ->next = NULL;
      free(pos);
      return 0;
   }
   pos->prev->next = pos -> next;
   pos->next->prev = pos -> prev;

   free(pos);
   return 0;
}

int Dlist_delete(Node** head,DATA data)
{
  Node* pos = Dlist_find(*head,data);
  return Dlist_delete_bypos(head,pos);
}

void Dlist_show(Node* head)
{
  Node* p = head;
  
  while(p)
  {
    printf("%6d",p->data);
    p = p -> next;
  }
  printf("\n");
}

void Dlist_free(Node** head)
{
  Node* p = *head,*q = NULL;
  
  while(p)
  {
     q = p;
     p = p -> next;
     free(q);
  }
  *head = NULL;
}

#include "Dlist.h"
#include <stdio.h>


int main(void)
{
  int del;
  int a[] = {1,3,5,7,9};
  Node* head = NULL;

  register int i = 0;

  for(; i< sizeof a /sizeof a[0]; i++)
  {
      if(Dlist_addtail(&head,a[i]) == -1)
      {
         printf("插入数据 %d 失败!\n",a[i]);
      }
  }
  Dlist_show(head);
  puts("=============");


  while(1)
  {
     puts("请输入要[查找/删除]的数据:");
     scanf("%d",&del);
     if(del == -1)
       break;
     //Node* pos = Dlist_find(head,del);
     //Dlist_insert(&head,pos,100);
     if(Dlist_insert(&head,del,888)== -1)
     {
        puts("删除失败!");
        continue;
     }    
     Dlist_show(head);
  }

  Dlist_free(&head);
  
  //list_show(head);
  
   return 0;
}

循环链表(Circular Linked list)

循环链表与双向链表相似,不同的地方在于:在链表的尾部增加一个指向头结点的指针,头结点也增加一个指向尾节点的指针,以及第一个节点指向头节点的指针,从而更方便索引链表元素。

#ifndef __DLIST_H__
#define __DLIST_H__

typedef int DATA;

typedef struct _node
{
  DATA data;
  struct _node *prev;
  struct _node *next;
}Node;

Node* list_init(DATA data);
void list_add_head(Node *new, Node *head);
void list_add_tail(Node *new, Node *head);
void list_show(Node*);

//void list_free(Node** head);

#endif
#include "dclist.h"
#include <stdio.h>
#include <stdlib.h>

Node* list_init(DATA data)
{
   Node* p = (Node*)malloc(sizeof(Node));
   if(!p)
      return NULL;
   p -> data = data;
   p -> prev = p;
   p -> next = p;
   return p;
}

static void __list_add(Node *new,Node *prev,Node *next)
{
        next->prev = new;
        new->next = next;
        new->prev = prev;
        prev->next =  new;
}

void list_add_head(Node *new, Node *head)
{
        __list_add(new, head, head->next);
}

void list_add_tail(Node *new, Node *head)
{
        __list_add(new, head->prev, head);
}

void list_show(Node* head)
{
  Node* p = head;
  while(p)
  {
     printf("%6d",p->data);
     p = p ->next;
     if(p == head)
      break;
  } 
  printf("\n");
}
#include "dclist.h"
#include <stdio.h>


int main(void)
{
  int del;
  int a[] = {1,3,5,7,9};
  Node* head = list_init(a[0]);

  register int i = 1;

  for(; i< sizeof a /sizeof a[0]; i++)
  {
      Node* new = list_init(a[i]);
      list_add_tail(new,head);
  }
  list_show(head);
  puts("=============");

/*
  while(1)
  {
     puts("请输入要[查找/删除]的数据:");
     scanf("%d",&del);
     if(del == -1)
       break;
     //Node* pos = Dlist_find(head,del);
     //Dlist_insert(&head,pos,100);
     if(Dlist_insert(&head,del,888)== -1)
     {
        puts("删除失败!");
        continue;
     }    
     Dlist_show(head);
  }

  Dlist_free(&head);
*/
  //list_show(head);
  
   return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值