数据结构之链表

Posted evilsnake

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之链表相关的知识,希望对你有一定的参考价值。

1:有头节点、单向、不循环链表

对于这种有头节点的单向不循环链表插入数据如下图:

1)头部插入

 

2)尾部插入

代码如下 :

 

  1   #include "stdafx.h"
  2   #include<iostream>
  3   
  4   using namespace std;
  5   
  6   typedef int DATA;
  7   typedef struct node* LIST;
  8   
  9   struct node
 10   {
 11       DATA data;
 12       struct node* next; //指向下一个节点的指针
 13   };
 14   
 15   //创建头节点
 16   LIST ListCreate()
 17   {
 18       struct node* head = (struct node*) malloc(sizeof(*head));
 19       if (head == NULL)
 20       {
 21           return NULL;
 22       }
 23       //这个时候只有头节点,head->next = null;数据为空
 24       head->next = NULL;
 25       //返回指向头节点的头指针
 26       return head; 
 27   }
 28   
 29   //判断一个链表是否是空链表
 30   int ListIsEmpty( LIST l)
 31   {
 32       return l->next == NULL;
 33   }
 34   
 35   //判断是不是链表的最后一个元素
 36   int ListIsLast(LIST l, struct node* p)
 37   {
 38       return p->next == NULL;
 39   }
 40   
 41   //插入链表元素 其实这个地方主要分为尾部插入,还是头部插入
 42   int ListInsert(LIST l, struct node* prev,const DATA *data ) 
 43   {
 44       struct node* cur = (struct node*)malloc(sizeof(*cur));
 45       if (cur == NULL)
 46       {
 47           return -1;
 48       }
 49       cur->data = *data;
 50       cur->next = prev->next;
 51       prev->next = cur;
 52       return 0;
 53   }
 54   
 55   int ListInsertHead(LIST l, const DATA* data)
 56   {
 57       return ListInsert(l,l,data);
 58   }
 59   
 60   int ListInsertTail( LIST l, const DATA* data )
 61   {
 62       struct node* tail = l;
 63       for (; tail->next != NULL; tail = tail->next); //空循环,找到尾节点
 64       return ListInsert(l,tail,data);
 65   }
 66   
 67   //查找
 68   struct node* ListFind(LIST l,const DATA* data )
 69   {
 70       struct node* p = l->next; //要考虑到空链表的情况就是p != null 从头节点的next开始查找,是因为头节点是不存放数据的,所以从头节点开始查找是没有意义的。
 71       for (; p != NULL && p->data != *data; p = p->next);
 72       return p;
 73   }
 74   
 75   //查找前驱节点
 76   struct node* ListFindPrev(LIST l, const DATA* data)
 77   {
 78       struct node* p = l; //查找前驱的话不能再指向头节点的下一个节点了,如果是一个空链表的话,就没有意义了,
 79   
 80       for (;p->next != NULL && p->next->data != *data; p = p->next);
 81   
 82       return p;
 83   }
 84   
 85   //删除链表元素
 86   int ListDelete(LIST l, const DATA* data)
 87   {
 88       //头节点是不能删除的
 89       struct node* prev = ListFindPrev(l,data); //这里就能处理到找不到或者是头节点的情况
 90       if (!ListIsLast(l, prev)) 
 91       {
 92           struct node *q = prev->next; //即q就是要删除的元素;
 93           prev->next = q->next;
 94           free(q);
 95           return 0;
 96       }
 97       return -1;
 98   }
 99   
100  //打印列表
101  void ListDisplay(LIST l)
102  {
103      struct node * p = l->next;
104      while (p != NULL )
105      {
106          printf("%d  ", p->data);
107          p = p->next;
108      }
109      printf("\\n");
110  }
111  
112  //销毁链表
113  void ListDispose(LIST l)
114  {
115      struct node *p = l->next;
116      struct node* q;
117      while (p != NULL)
118      {
119          q = p;
120          p = p->next;
121          free(q);
122      }
123  
124      free(l);
125  }
126  
127  int main()
128  {
129      int i;
130      DATA x;
131  
132      LIST head = ListCreate();
133      if (head == NULL)
134          return -1;
135  
136      //插入
137      for (i = 0; i < 6; i++)
138      {
139          x = i + 1;
140          //ListInsertHead(head,&x);
141          ListInsertTail(head,&x);
142      }
143      printf("链表里面的元素:: ");
144      ListDisplay(head);
145  
146      printf("从链表里面查找元素3\\n");
147      DATA y = 3;
148      //查找
149      struct node* p = ListFind(head,&y);
150      if (p == NULL)
151          printf("not find!!!\\n");
152      else
153          printf("data = %d\\n", p->data);
154  
155      printf("从链表里面删除元素3\\n");
156      ListDelete(head,&y);
157      ListDisplay(head);
158  
159      //
160      printf("销毁链表\\n");
161      ListDispose(head);
162      system("pause");
163  
164      return 0;
165  }
View Code

 2:有头节点、单向、循环链表

 1):头部插入

2)尾部插入

代码如下:

  1 // test04.cpp : Defines the entry point for the console application.
  2 //有头节点、单向、循环链表
  3 
  4 #include "stdafx.h"
  5 #include<iostream>
  6 
  7 using namespace std;
  8 
  9 struct node;
 10 typedef int DATA;
 11 typedef struct node* LIST;
 12 
 13 struct node
 14 {
 15     DATA data;
 16     struct node* next;
 17 };
 18 
 19 //创建头节点
 20 LIST ListCreate()
 21 {
 22     LIST head = (struct node*)malloc(sizeof(*head));
 23     if ( head == NULL )
 24     {
 25         return NULL;
 26     }
 27 
 28     head->next = head;
 29 
 30     return head;
 31 }
 32 
 33 //插入
 34 int ListInsert( LIST l, struct node* position, const DATA* data )
 35 {
 36     struct node* cur = (struct node*)malloc(sizeof(*cur));
 37     if ( cur == NULL )
 38     {
 39         return 0;
 40     }
 41     cur->data = *data;
 42     cur->next = position->next;
 43     position->next = cur;
 44 
 45     return 0;
 46 }
 47 
 48 //头部插入
 49 int ListHeadInsert(LIST l, const DATA* data)
 50 {
 51     return ListInsert(l,l,data);
 52 }
 53 
 54 //尾部插入
 55 int ListTailHead(LIST l, const DATA* data )
 56 {
 57     struct node* tail = l;
 58     for (; tail->next != l; tail = tail->next);
 59     return ListInsert(l,tail,data);
 60 }
 61 
 62 //查找
 63 struct node* ListFind( LIST l, const DATA* data )
 64 {
 65     struct node* p = l->next;
 66     for (; p != l && p->data != *data; p = p->next);
 67     return p;
 68 }
 69 
 70 struct node* ListFindPrev(LIST l, const DATA* data)
 71 {
 72     struct node* p = l;
 73     for (; p->next != l && p->next->data != *data; p = p->next);
 74     return p;
 75 }
 76 //删除
 77 int ListDelete( LIST l, const DATA* data )
 78 {
 79     struct node* prev = ListFindPrev( l, data );
 80     if ( prev != l) //不是头节点
 81     {
 82         struct node* q = prev->next;
 83         prev->next = q->next;
 84         free(q);
 85     }
 86     return 0;
 87 }
 88 
 89 //打印出来列表
 90 void ListDisplay(LIST l)
 91 {
 92     struct node* p = l->next;
 93     while (p != l)
 94     {
 95         printf("%d  ",p->data);
 96         p = p->next;
 97     }
 98     printf("\\n");
 99 }
100 
101 //消耗链表
102 void ListDispose(LIST l)
103 {
104     struct node* p = l->next;
105     struct node* q;
106     while (p != l)
107     {
108         q = p;
109         p = p->next;
110         free(q);
111     }
112     free(l);
113 }
114 
115 int main()
116 {
117     int i;
118     DATA x;
119     LIST head = NULL;
120     head = ListCreate();
121     if (head == NULL)
122     {
123         return 0;
124     }
125 
126     for (i = 0; i < 6; i++)
127     {
128         x = i + 1;
129         //ListHeadInsert(head,&x);
130         ListTailHead(head,&x);
131     }
132     //
133     printf("打印链表::\\n");
134     ListDisplay(head);
135 
136     DATA y = 3;
137     struct node* p = ListFind(head,&y);
138     if (p == NULL)
139         printf("not find!!!!");
140     else
141         printf("找到元素%d\\n", p->data);
142 
143     //删除元素
144     printf("删除元素之前,删除的元素是3\\n");
145     ListDelete(head,&y);
146     printf("删除元素之后\\n");
147     ListDisplay(head);
148 
149     ListDispose(head);
150 
151     system("pause");
152     return 0;
153 }
View Code

输出如下:

 

3:有头节点、双向、循环链表

1):头部插入

2):尾部插入

代码如下:

  1 // test02.cpp : Defines the entry point for the console application.
  2 //
  3 
  4 #include "stdafx.h"
  5 #include<iostream>
  6 
  7 using namespace std;
  8 
  9 typedef struct headnode* LIST;
 10 
 11 typedef void print_s(const void*);
 12 typedef int cmp(const void*, const void*);
 13 
 14 #define HEADINSERT 1
 15 #define TAILINSERT 2
 16 #define NAMESIZE 24
 17 //有头节点、双向、循环链表
 18 typedef struct stuinfo
 19 {
 20     int id;
 21     char name[NAMESIZE];
 22     int math;
 23 } DATA;
 24 
 25 struct listnode
 26 {
 27     void* data;
 28     struct listnode* prev;
 29     struct listnode* next;
 30 };
 31 struct headnode
 32 {
 33     int size;  //指向下面要插入数据的大小
 34     struct listnode head; //指向下一个节点的指针
 35 };
 36 
 37 //创建头节点
 38 LIST ListCreate( int size )
 39 {
 40     LIST handle = (struct headnode*)malloc(sizeof(*handle));
 41     if (handle == NULL)
 42     {
 43         return NULL;
 44     }
 45     handle->size = size;
 46     handle->head.data = NULL;
 47     handle->head.prev = handle->head.next = &handle->head;
 48 
 49     return handle;
 50 }
 51 
 52 //插入链表元素 其实这个地方主要分为尾部插入,还是头部插入
 53 int ListInsert( LIST l,const void *data, int mode ) 
 54 {
 55     struct listnode* cur = (struct listnode*)malloc(sizeof(*cur));
 56     if (cur == NULL)
 57     {
 58         return -1;
 59     }
 60     cur->data = malloc(l->size);
 61     if (cur->data == NULL)
 62     {
 63         free(cur);
 64         return -1;
 65     }
 66     memcpy(cur->data,data,l->size);
 67     if (mode == HEADINSERT) //首部插入
 68     {
 69         cur->prev = &l->head;
 70         cur->next = l->head.next;
 71         /////
 72         //cur->prev->next = cur;
 73         //cur->next->prev = cur;
 74     }
 75     else if (mode == TAILINSERT)
 76     {
 77         cur->next = &l->head;
 78         cur->prev = l->head.prev;
 79         ///////
 80         //cur->prev->next = cur;
 81         //cur->next->prev = cur; //可以把相同的两句话提取出来
 82     }
 83     else
 84     {
 85         free(cur->data);
 86         free(cur);
 87         return -1;
 88     }
 89     cur->prev->next = cur;
 90     cur->next->prev = cur;
 91 
 92     return 0;
 93 }
 94 
 95 
 96 //查找
 97 struct listnode* ListFind(LIST l,const void* key,cmp* funp)
 98 {
 99     struct listnode* p = l->head.next; //
100     for (; p != &l->head && funp(key, p->data); p = p->next);
Java数据结构线性表之链表

Java数据结构线性表之链表

Java数据结构线性表之链表

JavaScript数据结构之链表

JavaScript数据结构之链表

数据结构之链表