数据结构之链表
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 }
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 }
输出如下:
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数据结构线性表之链表