1.不带头的单链表
a. 函数声明
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int SDatatype; typedef struct SListNode { SDatatype data; struct SListNode* next; }SListNode; void SListPushBack(SListNode** pphead, SDatatype x);//单链表尾插 void SListPushFront(SListNode** pphead, SDatatype x);//单链表头插 void SListPopBack(SListNode** pphead);//单链表尾删 void SListPopFront(SListNode** pphead);//单链表头删 void SListNodePrint(SListNode* pphead);//打印 SListNode* SListFind(SListNode* phead, SDatatype x);//查找 void SListInsertFront(SListNode** pphead, SListNode* pos, SDatatype x);//在pos位置之前插入x void SListEraseFront(SListNode** pphead, SListNode* pos);//在pos位置
b.函数定义
#define _CRT_SECURE_NO_WARNINGS 1 #include"SList.h" SListNode *CreatNode(SDatatype x) { SListNode*newnode=(SListNode*)malloc(sizeof(SListNode)); if (newnode == NULL) { perror("CreatNode->:"); exit(-1); } newnode->data = x; newnode->next = NULL; return newnode; } void SListNodePrint(SListNode* pphead)//打印 { assert(pphead); SListNode* cur = pphead; while (cur) { printf("%d->", cur->data); cur = cur->next; } printf("NULL\n"); } void SListPushBack(SListNode** pphead, SDatatype x)//尾插 { SListNode*newnode=CreatNode(x); if ((*pphead) == NULL) { (*pphead) = newnode; return; } else { SListNode* tail = *pphead; while (tail->next != NULL) { tail = tail->next; } tail->next = newnode; } } void SListPushFront(SListNode** pphead, SDatatype x)//单链表头插 { SListNode* newnode = CreatNode(x); newnode->next=*pphead; *pphead = newnode; } void SListPopBack(SListNode** pphead)//单链表尾删 { assert(*pphead); if ((*pphead)->next = NULL) { free(*pphead); (*pphead) = NULL; } else { SListNode* prev = NULL; SListNode* tail = *pphead; while ((tail->next) != NULL) { prev = tail; tail = tail->next; } prev->next = NULL; free(tail); tail = NULL; } } void SListPopFront(SListNode** pphead)//单链表头删 { assert(*pphead); SListNode*temp = (*pphead)->next; free(*pphead); *pphead = temp; } SListNode* SListFind(SListNode* phead, SDatatype x)//查找 { SListNode* tail = phead; while (tail) { if (tail->data == x) { return tail; } else { tail = tail->next; } } return NULL; } void SListInsertFront(SListNode** pphead, SListNode* pos, SDatatype x) { // 严格限定pos一定是链表里面的一个有效节点 assert(pphead); assert(pos); assert(*pphead); if ((*pphead)==pos) { SListPushFront(pphead, x);//头插 } else { SListNode* newnode = CreatNode(x); SListNode* tail = *pphead; while (tail->next != pos) { tail = tail->next; } tail->next = newnode; newnode->next = pos; } } void SListEraseFront(SListNode** pphead, SListNode* pos)//在pos位置删除 { assert(pos); assert(*pphead); if (*pphead == pos) { SListPopFront(pphead);//头删 } else { SListNode* tail = *pphead; while (tail->next != pos) { tail = tail->next; } tail->next = pos->next; free(pos); pos = NULL; } }
2.带头的双向循环链表
a.函数声明
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int SDatatype; typedef struct LTNode { SDatatype data; struct LTNode* next; struct LTNode* prev; }LTNode; LTNode* SListInit(); void SListPrint(LTNode* phead); void SListPushBack(LTNode* phead, SDatatype x); void SListPopBack(LTNode* phead); void SListPushFront(LTNode* phead, SDatatype x); void SListPopFront(LTNode* phead); LTNode *SListFind(LTNode* phead, SDatatype x); void SListInsert(LTNode* pos, SDatatype x); void SListErse(LTNode* pos); void SListDestory(LTNode* phead);
b.函数定义
#define _CRT_SECURE_NO_WARNINGS 1 #include"List.h" LTNode* CreateNode(SDatatype x) { LTNode* newnode = (LTNode*)malloc(sizeof(LTNode)); if (newnode == NULL) { perror("CreateNode->:"); exit(-1); } newnode->data = x; newnode->next = NULL; newnode->prev = NULL; return newnode; } LTNode* SListInit() { LTNode* phead=CreateNode(-1); phead->next = phead; phead->prev = phead; return phead; } void SListPrint(LTNode* phead) { assert(phead); printf("哨兵位<=>"); LTNode* cur = phead->next; while (cur != phead) { printf("%d<=>", cur->data); cur = cur->next; } printf("\n"); } void SListPushBack(LTNode* phead, SDatatype x)//尾插 { assert(phead); LTNode* tail = phead->prev; LTNode* newnode= CreateNode(x); tail->next = newnode; newnode->prev = tail; newnode->next = phead; phead->prev =newnode; } void SListPopBack(LTNode* phead) { assert(phead); assert(phead->next != NULL); LTNode* tail = phead->prev; LTNode* tailPrev = tail->prev; phead->prev = tailPrev; tailPrev->next = phead; free(tail); tail = NULL; } void SListPushFront(LTNode* phead, SDatatype x) { assert(phead); LTNode* newnode = CreateNode(x); LTNode* first = phead->next; phead->next = newnode; newnode->prev = phead; newnode->next = first; first->prev = newnode; } void SListPopFront(LTNode* phead) { LTNode* first = phead->next; LTNode* sencond = first->next; phead->next = sencond; sencond->prev = phead; free(first); } LTNode* SListFind(LTNode* phead,SDatatype x) { assert(phead); assert(phead->next); LTNode* cur = phead->next; while (cur != phead) { if (cur->data == x) return cur; cur = cur->next; } return NULL; } void SListInsert(LTNode* pos, SDatatype x) { assert(pos); LTNode* newnode = CreateNode(x); LTNode* PosPrev = pos->prev; PosPrev->next = newnode; newnode->prev = PosPrev; newnode->next = pos; pos->prev = newnode; } void SListErse(LTNode* pos) { LTNode* Prev = pos->prev; LTNode* Next = pos->next; Prev->next = Next; Next->prev = Prev; } void SListDestory(LTNode* phead) { assert(phead); LTNode* cur = phead; while (cur->next) { LTNode* Next = cur->next; free(cur); cur = Next; } free(phead); phead = NULL; }
总结:单链表较双向循环链表的程序难一点,因为要考虑链表为空时,或只有一个节点时的特殊情况,但是经常在oj题中出现的都是单链表,且不带头节点,应用较广。
双向循环链表程序写起来非常简单,不用单独处理特殊情况。