081103_链表的C语言实现之单链表的实现

合集下载

c语言实现--带头结点单链表操作

c语言实现--带头结点单链表操作

c语⾔实现--带头结点单链表操作可能是顺序表研究的细致了⼀点,单链表操作⼀下⼦就实现了。

这⾥先实现带头结点的单链表操作。

⼤概有以下知识点.1;结点:结点就是单链表中研究的数据元素,结点中存储数据的部分称为数据域,存储直接后继地址的部分称为指针域。

2;结点⽰意图:3;头指针:头指针始终指向链表第⼀个元素,当有头结点时头结点就是链表第⼀个元素。

头指针具有标识左右,故头指针命名为链表的名字,这⾥为linklist。

头指针是⼀定存在的。

4;头结点:引⼊头结点的⽬的是,将链表⾸元结点的插⼊和删除操作与其他结点的插⼊和删除操作统⼀起来。

(即头指针地址不在发⽣变化)5;单链表结点结构体表⽰:1struct LNode2 {3int data; //姑且认为其数据为整型4struct LNode * next;5 };67 typedef struct LNode * linklist6;单链表的操作集合,头⽂件 defs.h1 #ifndef _DEFS_H_2#define _DEFS_H_34 #include<stdio.h>5 #include<stdlib.h>6 #include<malloc.h>78struct LNode //单链表结点的定义9 {10int data;11struct LNode * next;12 }13 typedef struct LNode * linklist1415//操作集合16void InitList(linklist *L); //申请头结点,头指针地址改变17void DestroyList(linklist *L); //须释放头结点,头指针地址改变18void ClearList(linklist L); //保留头结点,头指针地址不变19void ListEmpty(linklist L);20int ListLength(linklist L);21int GetElem(linklist L, int i, int *e);22int LocateElem(linklist L, int e);23int PriorElem(linklist L, int cur_e, int *pri_e);24int NextElem(linklist L, int cur_e, int *nex_e);25int ListInsert(linklist L, int i, int e); //插⼊不改变头指针的值26int ListDelete(linklist L, int i, int *e); //删除操作也不改变头指针的值27void TravelList(linklist L);28#endif7;InitList操作实现1 #include"defs.h"23void InitList(linklist *L) //接受头指针的地址值4 {5 *L = (linklist)malloc(sizeof(struct LNode)); //*L表⽰头指针67if (*L == NULL)8 {9 printf("分配结点失败。

单链表的基本操作

单链表的基本操作

单链表的基本操作《》⼀节我们学习了如何使⽤存储数据元素,以及如何使⽤ C 语⾔创建链表。

本节将详细介绍对链表的⼀些基本操作,包括对链表中数据的添加、删除、查找(遍历)和更改。

注意,以下对链表的操作实现均建⽴在已创建好链表的基础上,创建链表的代码如下所⽰:1. //声明节点结构2. typedef struct Link{3. int elem;//存储整形元素4. struct Link *next;//指向直接后继元素的指针5. }link;6. //创建链表的函数7. link * initLink(){8. link * p=(link*)malloc(sizeof(link));//创建⼀个头结点9. link * temp=p;//声明⼀个指针指向头结点,⽤于遍历链表10. //⽣成链表11. for (int i=1; i<5; i++) {12. //创建节点并初始化13. link *a=(link*)malloc(sizeof(link));14. a->elem=i;15. a->next=NULL;16. //建⽴新节点与直接前驱节点的逻辑关系17. temp->next=a;18. temp=temp->next;19. }20. return p;21. }从实现代码中可以看到,该链表是⼀个具有头节点的链表。

由于头节点本⾝不⽤于存储数据,因此在实现对链表中数据的"增删查改"时要引起注意。

链表插⼊元素同⼀样,向链表中增添元素,根据添加位置不同,可分为以下 3 种情况:插⼊到链表的头部(头节点之后),作为⾸元节点;插⼊到链表中间的某个位置;插⼊到链表的最末端,作为链表中最后⼀个数据元素;虽然新元素的插⼊位置不固定,但是链表插⼊元素的思想是固定的,只需做以下两步操作,即可将新元素插⼊到指定的位置:1. 将新结点的 next 指针指向插⼊位置后的结点;2. 将插⼊位置前结点的 next 指针指向插⼊结点;例如,我们在链表{1,2,3,4}的基础上分别实现在头部、中间部位、尾部插⼊新元素 5,其实现过程如图 1 所⽰:图 1 链表中插⼊元素的 3 种情况⽰意图从图中可以看出,虽然新元素的插⼊位置不同,但实现插⼊操作的⽅法是⼀致的,都是先执⾏步骤 1 ,再执⾏步骤 2。

C语言单链表实现方法详解

C语言单链表实现方法详解

C语⾔单链表实现⽅法详解本⽂实例讲述了C语⾔单链表实现⽅法。

分享给⼤家供⼤家参考,具体如下:slist.h#ifndef __SLIST_H__#define __SLIST_H__#include<cstdio>#include<malloc.h>#include<assert.h>typedef int ElemType;typedef struct Node { //定义单链表中的结点信息ElemType data; //结点的数据域struct Node *next; //结点的指针域}Node,*PNode;typedef struct List { //定义单链表的链表信息PNode first; //first指向单链表中的第⼀个结点PNode last; //last指向单链表中的最后⼀个结点size_t size; //记录单链表中的结点个数}List;void InitList(List *list);//初始化单链表void push_back(List *list, ElemType x);//在单链表的末尾插⼊元素void push_front(List *list, ElemType x);//在单链表的头部插⼊元素void show_list(List *list);//打印单链表void pop_back(List *list);//删除单链表的最后⼀个元素void pop_front(List *list);//删除单链表的第⼀个元素void insert_val(List *list, ElemType val);//将数据元素插⼊到单链表中(要求此时单链表中的数据元素顺序排列)Node* find(List *list, ElemType x);//查找单链表中数据值为x的结点int length(List *list);//求单链表的长度void delete_val(List *list, ElemType x);//按值删除单链表中的某个数据元素void sort(List *list);//对单链表进⾏排序void reverse(List *list);//逆置单链表void clear(List *list);//清除单链表void destroy(List *list);//摧毁单链表#endif //__SLIST_H__slist.cpp#include"slist.h"void InitList(List *list) {list->first = list->last = (Node*)malloc(sizeof(Node)); //头结点assert(list->first != NULL);list->first->next = NULL;list->size = 0;}void push_back(List *list, ElemType x) {//step 1:创建⼀个新的结点Node *s = (Node*)malloc(sizeof(Node));assert(s != NULL);s->data = x;s->next = NULL;//step 2:将新结点插⼊单链表的表尾list->last->next = s;list->last = s;//step 3:更新单链表的长度list->size++;}void push_front(List *list, ElemType x) {//step 1:创建⼀个新的结点Node *s = (Node*)malloc(sizeof(Node));assert(s != NULL);s->data = x;s->next = NULL;//step 2:将新结点插⼊单链表的表头s->next = list->first->next;list->first->next = s;//step 3:判断插⼊的结点是否是单链表的第⼀个结点,若是更新链表的尾指针if (list->size == 0)list->last = s;//step 4:更新单链表的长度list->size++;}void show_list(List *list) {//step 1:指针p指向单链表的第⼀个结点Node *p = list->first->next;//step 2:循环打印结点的信息while (p != NULL) {printf("%d->", p->data);p = p->next;}printf("Nul.\n");}void pop_back(List *list) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:定义指针p使其指向⽬标结点的前⼀个结点Node *p = list->first;//从头结点开始while (p->next != list->last)p = p->next;//step 3:删除⽬标结点free(list->last);list->last = p;list->last->next = NULL;//step 4:更新单链表的长度list->size--;}void pop_front(List *list) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:定义指针p使其指向⽬标结点的前⼀个结点Node *p = list->first->next;//step 3:删除⽬标结点list->first->next = p->next;free(p);//step 4:判断删除的结点是否是单链表的最后⼀个结点,若是则更新单链表的尾指针 if (list->size == 1)list->last = list->first;//step 4:更新单链表的长度list->size--;}void insert_val(List *list, ElemType x) {//step 1:创建⼀个新的结点Node *s = (Node*)malloc(sizeof(Node));assert(s != NULL);s->data = x;s->next = NULL;//step 2:定义指针p使其指向待插⼊位置的前⼀个结点Node *p = list->first;//从头结点开始while (p->next != NULL && p->next->data < s->data)p = p->next;//step 3:判断结点的待插⼊位置是否是表尾,若是则更新单链表的尾指针if (p->next == NULL)list->last = s;//step 4:插⼊结点s->next = p->next;p->next = s;//step 5:更新单链表长度list->size++;}Node* find(List *list, ElemType x) {//step 1:指针p指向单链表的第⼀个结点Node *p = list->first->next;//step 2:按照循环顺序查找链表结点while (p != NULL && p->data != x)p = p->next;return p;}int length(List *list) {return list->size;}void delete_val(List *list, ElemType x) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:确定结点在单链表中的位置,并判断其是否存在于单链表中Node *p = find(list, x);if (p == NULL) {printf("要删除的数据不存在!\n");return;}//step 3:判断结点位置是否是表尾if (p == list->last)//是表尾pop_back(list);else {//不是表尾Node *q = p->next;p->data = q->data;p->next = q->next;free(q);list->size--;}}void sort(List *list) {//step 1:判断单链表中的结点数是否为0或1if (list->size == 0 || list->size == 1) return;//step 2:将单链表中第⼀个结点之后的链表部分截出,⽅便重新按顺序插⼊链表之中Node *s = list->first->next; // 指针s指向单链表的第⼀个节点Node *p = s->next;//q指向s后⾯的结点list->last = s;//单链表的尾指针指向单链表的第⼀个结点list->last->next = NULL;//截断链表//step 3:将截出的链表中的结点根据其数据域⼤⼩重新插⼊到原来链表中while (p != NULL) {s = p;p = p->next;Node *q = list->first;while (q->next != NULL && q->next->data < s->data)q = q->next;if (q->next == NULL)//判断q此时指向的是否是单链表的最后⼀个结点,若是则更新链表的尾指针list->last = s;//将结点重新插⼊链表s->next = q->next;q->next = s;}}void reverse(List *list) {//step 1:判断单链表中的结点数是否为0或1if (list->size == 0 || list->size == 1) return;//step 2:将单链表中第⼀个结点之后的链表部分截出,然后将截出的链表中的结点按头插法重新插⼊到原链表中 Node *p = list->first->next;Node *q = p->next;list->last = p;list->last->next = NULL;while (q != NULL) {p = q;q = q->next;p->next = list->first->next;list->first->next = p;}}void clear(List *list) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:释放单链表中的每⼀个结点Node *p = list->first->next;while (p != NULL) {list->first->next = p->next;free(p);p = list->first->next;}//step 3:头指针和尾指针重新都指向头结点list->last = list->first;//step 4:更新链表长度list->size = 0;}void destroy(List *list) {//step 1:清空单链表clear(list);//step 2:释放头结点free(list->first);//step 3:头指针和尾指针都赋值为空list->first = list->last = NULL;}main.cpp#include"slist.h"void main() {List mylist;InitList(&mylist);ElemType item;Node *p = NULL;int select = 1;while (select) {printf("*******************************************\n"); printf("*[1] push_back [2] push_front *\n");printf("*[3] show_list [4] pop_back *\n");printf("*[5] pop_front [6] insert_val *\n");printf("*[7] find [8] length *\n");printf("*[9] delete_val [10] sort *\n");printf("*[11] reverse [12] clear *\n");printf("*[13*] destroy [0] quit_system *\n"); printf("*******************************************\n"); printf("请选择:>>");scanf("%d", &select);if (select == 0) break;switch (select) {case 1:printf("请输⼊要插⼊的数据(-1结束):>");while (scanf("%d", &item), item != -1) {push_back(&mylist, item);}break;case 2:printf("请输⼊要插⼊的数据(-1结束):>");while (scanf("%d", &item), item != -1) {push_front(&mylist, item);}break;case 3:show_list(&mylist);break;case 4:pop_back(&mylist);break;case 5:pop_front(&mylist);break;case 6:printf("请输⼊要插⼊的数据:>");scanf("%d", &item);insert_val(&mylist, item);break;case 7:printf("请输⼊要查找的数据:>");scanf("%d", &item);p = find(&mylist, item);if (p == NULL)printf("要查找的数据在单链表中不存在!\n"); break;case 8:printf("单链表的长度为%d\n", length(&mylist)); break;case 9:printf("请输⼊要删除的值:>");scanf("%d", &item);delete_val(&mylist, item);break;case 10:sort(&mylist);break;case 11:reverse(&mylist);break;case 12:clear(&mylist);break;//case 13://destroy(&mylist);//break;default:printf("选择错误,请重新选择!\n");break;}}destroy(&mylist); //程序结束,摧毁链表}附:单链表优化版本slist.h#ifndef __SLIST_H__#define __SLIST_H__#include<cstdio>#include<malloc.h>#include<assert.h>typedef int ElemType;typedef struct Node { //定义单链表中的结点信息ElemType data; //结点的数据域struct Node *next; //结点的指针域}Node,*PNode;typedef struct List { //定义单链表的链表信息PNode first; //first指向单链表中的第⼀个结点PNode last; //last指向单链表中的最后⼀个结点size_t size; //记录单链表中的结点个数}List;void InitList(List *list);//初始化单链表void push_back(List *list, ElemType x);//在单链表的末尾插⼊元素void push_front(List *list, ElemType x);//在单链表的头部插⼊元素void show_list(List *list);//打印单链表void pop_back(List *list);//删除单链表的最后⼀个元素void pop_front(List *list);//删除单链表的第⼀个元素void insert_val(List *list, ElemType val);//将数据元素插⼊到单链表中(要求此时单链表中的数据元素顺序排列)Node* find(List *list, ElemType x);//查找单链表中数据值为x的结点int length(List *list);//求单链表的长度void delete_val(List *list, ElemType x);//按值删除单链表中的某个数据元素void sort(List *list);//对单链表进⾏排序void reverse(List *list);//逆置单链表void clear(List *list);//清除单链表void destroy(List *list);//摧毁单链表//代码优化Node* CreateNode(ElemType x); //创建⼀个单链表结点Node* begin(List *list); //返回单链表的第⼀个结点Node* end(List *list); //返回单链表中最后⼀个结点的下⼀个结点void insert(List *list, Node *pos, ElemType x); //在单链表的特定位置(pos)插⼊新的结点#endif //__SLIST_H__slist.cpp#include"slist.h"void InitList(List *list) {list->first = list->last = (Node*)malloc(sizeof(Node)); //头结点assert(list->first != NULL);list->first->next = NULL;list->size = 0;}//push_back的优化void push_back(List *list, ElemType x) {insert(list, end(list), x);}//push_front的优化void push_front(List *list, ElemType x) {insert(list, begin(list), x);}void show_list(List *list) {//step 1:指针p指向单链表的第⼀个结点Node *p = list->first->next;//step 2:循环打印结点的信息while (p != NULL) {printf("%d->", p->data);p = p->next;}printf("Nul.\n");}void pop_back(List *list) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:定义指针p使其指向⽬标结点的前⼀个结点Node *p = list->first;//从头结点开始while (p->next != list->last)p = p->next;//step 3:删除⽬标结点free(list->last);list->last = p;list->last->next = NULL;//step 4:更新单链表的长度list->size--;}void pop_front(List *list) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:定义指针p使其指向⽬标结点的前⼀个结点Node *p = list->first->next;//step 3:删除⽬标结点list->first->next = p->next;free(p);//step 4:判断删除的结点是否是单链表的最后⼀个结点,若是则更新单链表的尾指针 if (list->size == 1)list->last = list->first;//step 4:更新单链表的长度list->size--;}//insert_val的优化void insert_val(List *list, ElemType x) {//step 1:创建⼀个新的结点Node *s = CreateNode(x);//step 2:定义指针p使其指向待插⼊位置的前⼀个结点Node *p = list->first;//从头结点开始while (p->next != NULL && p->next->data < s->data)p = p->next;//step 3:判断结点的待插⼊位置是否是表尾,若是则更新单链表的尾指针if (p->next == NULL)list->last = s;//step 4:插⼊结点s->next = p->next;p->next = s;//step 5:更新单链表长度list->size++;}Node* find(List *list, ElemType x) {//step 1:指针p指向单链表的第⼀个结点Node *p = list->first->next;//step 2:按照循环顺序查找链表结点while (p != NULL && p->data != x)p = p->next;return p;}int length(List *list) {return list->size;}void delete_val(List *list, ElemType x) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:确定结点在单链表中的位置,并判断其是否存在于单链表中Node *p = find(list, x);if (p == NULL) {printf("要删除的数据不存在!\n");return;}//step 3:判断结点位置是否是表尾if (p == list->last)//是表尾pop_back(list);else {//不是表尾Node *q = p->next;p->data = q->data;p->next = q->next;free(q);list->size--;}}void sort(List *list) {//step 1:判断单链表中的结点数是否为0或1if (list->size == 0 || list->size == 1) return;//step 2:将单链表中第⼀个结点之后的链表部分截出,⽅便重新按顺序插⼊链表之中Node *s = list->first->next; // 指针s指向单链表的第⼀个节点Node *p = s->next;//q指向s后⾯的结点list->last = s;//单链表的尾指针指向单链表的第⼀个结点list->last->next = NULL;//截断链表//step 3:将截出的链表中的结点根据其数据域⼤⼩重新插⼊到原来链表中while (p != NULL) {s = p;p = p->next;Node *q = list->first;while (q->next != NULL && q->next->data < s->data)q = q->next;if (q->next == NULL)//判断q此时指向的是否是单链表的最后⼀个结点,若是则更新链表的尾指针list->last = s;//将结点重新插⼊链表s->next = q->next;q->next = s;}}void reverse(List *list) {//step 1:判断单链表中的结点数是否为0或1if (list->size == 0 || list->size == 1) return;//step 2:将单链表中第⼀个结点之后的链表部分截出,然后将截出的链表中的结点按头插法重新插⼊到原链表中 Node *p = list->first->next;Node *q = p->next;list->last = p;list->last->next = NULL;while (q != NULL) {p = q;q = q->next;p->next = list->first->next;list->first->next = p;}}void clear(List *list) {//step 1:判断单链表是否为空if (list->size == 0) return;//step 2:释放单链表中的每⼀个结点Node *p = list->first->next;while (p != NULL) {list->first->next = p->next;free(p);p = list->first->next;}//step 3:头指针和尾指针重新都指向头结点list->last = list->first;//step 4:更新链表长度list->size = 0;}void destroy(List *list) {//step 1:清空单链表clear(list);//step 2:释放头结点free(list->first);//step 3:头指针和尾指针都赋值为空list->first = list->last = NULL;}//优化Node* CreateNode(ElemType x) {Node *s = (Node*)malloc(sizeof(Node));assert(s != NULL);s->data = x;s->next = NULL;return s;}Node* begin(List *list) {return list->first->next;}Node* end(List *list) {return list->last->next;}void insert(List *list, Node *pos, ElemType x) {//step 1:创建⼀个新的结点Node *s = CreateNode(x);//step 2:确定带插⼊位置Node *p = list->first;while (p->next != pos)p = p->next;//step 3:插⼊结点s->next = p->next;p->next = s;//step 4:判断结点是否插⼊到链表的表尾,若是则更新单链表的表尾指针 if (pos == NULL)list->last = s;//step 5:更新单链表长度list->size++;}main.cpp#include"slist.h"void main() {List mylist;InitList(&mylist);ElemType item;Node *p = NULL;int select = 1;while (select) {printf("*******************************************\n");printf("*[1] push_back [2] push_front *\n");printf("*[3] show_list [4] pop_back *\n");printf("*[5] pop_front [6] insert_val *\n");printf("*[7] find [8] length *\n");printf("*[9] delete_val [10] sort *\n");printf("*[11] reverse [12] clear *\n");printf("*[13*] destroy [0] quit_system *\n");printf("*******************************************\n");printf("请选择:>>");scanf("%d", &select);if (select == 0) break;switch (select) {case 1:printf("请输⼊要插⼊的数据(-1结束):>");while (scanf("%d", &item), item != -1) {push_back(&mylist, item);}break;case 2:printf("请输⼊要插⼊的数据(-1结束):>");while (scanf("%d", &item), item != -1) {push_front(&mylist, item);}break;case 3:show_list(&mylist);break;case 4:pop_back(&mylist);break;case 5:pop_front(&mylist);break;case 6:printf("请输⼊要插⼊的数据:>");scanf("%d", &item);insert_val(&mylist, item);break;case 7:printf("请输⼊要查找的数据:>");scanf("%d", &item);p = find(&mylist, item);if (p == NULL)printf("要查找的数据在单链表中不存在!\n");break;case 8:printf("单链表的长度为%d\n", length(&mylist));break;case 9:printf("请输⼊要删除的值:>");scanf("%d", &item);delete_val(&mylist, item);break;case 10:sort(&mylist);break;case 11:reverse(&mylist);break;case 12:clear(&mylist);break;//case 13://destroy(&mylist);//break;default:printf("选择错误,请重新选择!\n");break;}}destroy(&mylist); //程序结束,摧毁链表}希望本⽂所述对⼤家C语⾔程序设计有所帮助。

单链表(c语言实现)贼详细

单链表(c语言实现)贼详细

单链表(c语⾔实现)贼详细直接上代码吧#include<stdio.h>#include<malloc.h>/*单链表特点:它是⼀种动态的储存结构,链表中每个节点占⽤的储存空间不是预先分配的,⽽是运⾏时系统根据需求⽣成的*/typedef struct lnode{int data;struct lnode *next;}lnode,*linklist;//结点定义/*关于头指针的⼀点说明:linklist L;外⾯⽤头指针来标识⼀个单链表,如单链表L,单链表H等,是指链表的第⼀个节点的地址被记录在指针变量L,H中,头指针为NULL时,表⽰⼀个空的单链表,需要进⼀步指出的是:上⾯定义的lnode是节点的类型,linklist是指向lnode节点的指针的类型,为了增强程序的可读性,通常将标识⼀个链表的头指针说明为linklist类型的变量*/linklist creat_linklist_insert_head_nohead(){linklist l=NULL;//定义头指针变量llnode *s;//新建⼀个节点int flag=-1;//输⼊停⽌标志位printf("输⼊整型数据,数据以空格隔开,输⼊数据为-1的时候表⽰输⼊截⽌\n");while(1){int x;scanf("%d",&x);if(x==flag)break;s=(lnode*)malloc(sizeof(lnode));//对s节点申请储存空间s->data=x;//赋值s->next=l;//s节点的next指向头指针l=s;//头指针指向新建⽴的s节点,因为这是在单链表的头部插⼊数据}return l;}//创建⼀个单链表,通过在头部插⼊数据,不含空的头节点//-------------------------------------------------------------------------------------------------------------///*在单链表的表头插⼊,只要x!=flag,就是⼀直申请s结点,从⽽可以⼀直在表头插⼊,其中l=s是最重要的,因为这是将s插⼊到l的表头,因为是在头部插⼊,所以只要⼀个头指针就可以,若是在单链表的尾部插⼊,那么就需要尾部指针关于此函数使⽤的⼀点说明:我们输⼊数据 1 2 3 4 5的时候,输出的是 5 4 3 2 1,因为我们是在头部插⼊数据的*///-------------------------------------------------------------------------------------------------------------//linklist creat_linklist_insert_end_yeshead(){linklist l=NULL,r=NULL;//定义头指针变量和尾指针变量lnode *s;//定义新建节点int flag=-1;//输⼊结束标志位printf("输⼊整型数据,数据以空格隔开,输⼊数据为-1的时候表⽰输⼊截⽌\n");while(1){int x;scanf("%d",&x);if(x==flag)//输⼊数据等于输⼊结束标志位则跳出循环break;s=(lnode*)malloc(sizeof(lnode));//申请内存空间s->data=x;//赋值if(l==NULL)//单链表为空l=s;//则将头指针指向新建节点elser->next=s;//不空的话则将尾指针的next指向s,因为如果不空的话,尾指针指向的肯定是⼀个数据节点,尾指针的next指向s是为了将两个数据节点连接起来r=s;//尾指针移动到新插⼊的节点上}if(r!=NULL)//有数据r->next=NULL;//尾指针的next指向空,说明尾指针后⾯没有数据了,⽬的的为了保证单链表尾指针逻辑的合理性return l;}//建⽴单链表且在链表尾部插⼊数据,含空的头节点//-----------------------------------------------------------------------------------------------------------------------///*在单链表的尾部插⼊,只要没有输⼊结束的标志,就⼀直申请s结点,然后把x赋给s结点的data域,l=s是为了第⼀个结点的结点的处理,因为在此之前l是⼀个空表,然后因为不断有新的结点⽣成,所以就是不断把新的s结点赋给r的next,这样就不断有s结点加⼊到了单链表中间,然后最重要的是每次新的结点加⼊到单链表中后要把r尾指针向后⾯移动,就是⽂中的r=s;关于此函数的⼀点说明:输⼊数据 1 2 3 4 5,输出还是 1 2 3 4 5,⽽不是 5 4 3 2 1,因为我们插⼊数据是在链表尾部插⼊的*///-----------------------------------------------------------------------------------------------------------------------//int length_linklist_yeshead(linklist l){linklist p=l;int j=1;while(p->next){j++;p=p->next;}return j;}//求单链表的表长,针对含有空的头节点的单链表int length_linklist_nohead(linklist l){lnode *p=l;int j=0;while(p){j++;p=p->next;}return j;}//求链表的表长,针对不含空的头节点的单链表lnode *get_linklist(linklist l,int i){lnode *p=l;int j=0;while(p!=NULL&&j<i){p=p->next;j++;}if(j==i)return p;elsereturn NULL;}//单链表的查找第i个元素结点,*p=l就是使p指针指向l链表;lnode *locate_linklist(linklist l,int x){lnode *p=l->next;//l为头节点while(p!=NULL&&p->data!=x)p=p->next;return p;}//单链表查找值为x的结点,找到后返回指向这个结点的指针;以后时刻要记得l为头指针,因为定义了头指针⽐没有定义头指针要⽅便许多;int insert_linklist(linklist l,int i,int x){lnode *p,*s;p=get_linklist(l,i-1);//找到第i-1个结点if(p==NULL){printf("i错误");return0;}elses=(lnode*)malloc(sizeof(lnode));s->data=x;s->next=p->next;p->next=s;return1;}//单链表的第i个结点后⾯的插⼊,重要的是申请,封装s结点,int del_linklist(linklist l,int i){i--;linklist p,s;p=get_linklist(l,i-1);if(p==NULL){printf("该i-1节点不存在");return -1;}else if(p->next==NULL){printf("第i个结点不存在");return0;}else{s=p->next;p->next=s->next;free(s);return1;}}//单链表中删除第i个结点,那么就先要找到i个结点的前驱,也就是第i-1个结点,同理单链表中的插⼊也要知道其前驱结点,所以单链表中的头节点的重要性就可想⽽知了void printf_linklist(lnode *plisthead){lnode *ptemp=plisthead;while(ptemp){printf("%d\t",ptemp->data);ptemp=ptemp->next;}printf("\n");}//链表打印函数int main(){/*linklist l=creat_linklist_insert_end_yeshead();printf("%d\n",length_linklist_yeshead(l));insert_linklist(l,2,100);//第⼆个结点的后⾯插⼊100printf_linklist(l);del_linklist(l,4);//删除第四个结点printf_linklist(l);*//*linklist l=creat_linklist_insert_head_nohead();printf("%d\n",length_linklist_nohead(l));insert_linklist(l,2,100);printf_linklist(l);del_linklist(l,4);printf_linklist(l);*/return0;}。

单链表的C语言实现

单链表的C语言实现
exchange = 1;
}
currentnode = currentnode ->next ;
}
if (exchange ==0)
return sl;
}
return sl;
}
/*求链表的长度*/
int GetLength(SLink *sl)
/*
单链表的C语言实现
struct list {
usr_type key;
usr_type content;
... //自己根据需要增删
struct list *next;
};//usr_type 的类型你自己定义就好
实现单链表的创建、插入、删除、关键字查询、两个单链表的合并,尝试按关键字进行排序。
{
currentnode = currentnode->next ;
currentloction ++;
}
newnode ->next = currentnode ->next;
currentnode ->next = newnode;
return 1; /*插入成ห้องสมุดไป่ตู้,返回1*/
currentnode = sl;
if (location < 1 || location > GetLength(sl)+1)
return 0; /*插入位置不正确,失败,返回0*/
while (currentloction<location) /*在单键表上找到插入位置的前一个结点*/
for(int i=0;i<len-1;i++)

单链表(C语言实现)

单链表(C语言实现)

单链表(C语⾔实现)链表结构:SList.h//--------------------------------------------------------------------------/***功能:应⽤C语⾔实现单链表的各项操作****** 1:建⽴节点** 2:打印单链表** 3:尾插** 4:尾删** 5:头插** 6:头删** 7:清空整个链表** 8:获取链表长度** 9:查找数据** 10:在某位置后插⼊数据** 11:删除某位置的数据** 12:删除⼀个⽆头单链表的⾮尾节点** 13:在⽆头单链表的⼀个⾮头节点前插⼊⼀个节点** 14:查找中间节点** 15:查找倒数第k个节点(要求只能遍历⼀次)** 16:倒着打印单链表** 17:逆置单链表** 18:合并两个有序链表(合并后依然有序)** 19:冒泡排序****** By :Lynn-Zhang***///---------------------------------------------------------------------------#pragma oncetypedef int DataType;typedef struct SListNode{DataType data; // 数据struct SListNode* next; //指向下⼀个节点的指针}SListNode;// 如果要修改链表就必须加引⽤SListNode* _BuyNode(DataType x); //建⽴节点void PrintSlist(SListNode* pHead); //打印单链表void PushBack(SListNode* & pHead, DataType x); //尾插(这⾥⽤了引⽤,指明是list的别名,调⽤时传参,不⽤传地址)(引⽤在.c⽂件中不可⽤) //void PushBack(SListNode** pHead, DataType x); // 这⾥的第⼀个参数指向链表第⼀个节点的指针的地址(调⽤时传参,传的是地址)void PopBack(SListNode* & pHead); //尾删void PushFront(SListNode* & pHead, DataType x); //头插void PopFront(SListNode* & pHead); //头删void DestoryList(SListNode*& pHead); //清空整个链表int GetSize(SListNode* pHead); //获取链表长度SListNode* Find(SListNode* pHead, DataType x); //查找数据void Insert(SListNode* pos, DataType x); //在某位置后插⼊数据void Erase(SListNode*& pHead, SListNode* pos); //删除某位置的数据void DelNonTailNode(SListNode* pos); //删除⼀个⽆头单链表的⾮尾节点void InsertFrontNode(SListNode* pos, DataType x); // 在⽆头单链表的⼀个⾮头节点前插⼊⼀个节点SListNode* FindMidNode(SListNode* pHead); //查找中间节点SListNode* FindKNode(SListNode* pHead, int k); //查找倒数第k个节点(要求只能遍历⼀次)void PrintTailToHead(SListNode* pHead); //倒着打印单链表(递归)//SListNode* Reverse_(SListNode* pHead); //逆置单链表(需要接收返回值),原链表会被改void Reverse(SListNode*& pHead); // 将原链表逆置SListNode* Merge(SListNode* pHead1, SListNode* pHead2); //合并两个有序链表(合并后依然有序)(递归)void Sort(SListNode* pHead); //冒泡排序SList.cpp#include"SList.h"#include <stdio.h>#include<assert.h>#include <malloc.h>SListNode* _BuyNode(DataType x) //建⽴节点{SListNode* tmp = (SListNode*)malloc(sizeof(SListNode)); tmp->data = x;tmp->next = NULL;return tmp;}void PrintSlist(SListNode* pHead) // 打印单链表{SListNode* cur = pHead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");}//void PushBack(SListNode** ppHead, DataType x) //尾插//{// assert(ppHead);//// 1.空//// 2.不为空// if(*ppHead == NULL)// {// *ppHead = _BuyNode(x);// }// else// {//// 找尾// SListNode* tail = *ppHead;// while(tail->next != NULL)// {// tail = tail->next;// }//// tail->next = _BuyNode(x);// }//}void PushBack(SListNode* & pHead, DataType x) //尾插{// 1.空// 2.不为空if (pHead == NULL){pHead = _BuyNode(x);}else{// 找尾SListNode* tail = pHead;while (tail->next != NULL){tail = tail->next;}tail->next = _BuyNode(x);}}void PopBack(SListNode* & pHead) // 尾删{//// 1.空// 2.⼀个节点// 3.多个节点//if (pHead == NULL){return;}else if (pHead->next == NULL){free(pHead);pHead = NULL;}else{SListNode* tail = pHead;SListNode* prev = NULL;while (tail->next){prev = tail;tail = tail->next;}free(tail);prev->next = NULL;}}void PushFront(SListNode* & pHead, DataType x) //头插{// 1.空// 2.不空if (pHead == NULL){pHead = _BuyNode(x);}else{SListNode* tmp = _BuyNode(x);tmp->next = pHead;pHead = tmp;}}void PopFront(SListNode*& pHead) //头删{//// 1.空// 2.⼀个节点// 3.⼀个以上的节点//if (pHead == NULL){return;}else if (pHead->next == NULL){free(pHead);pHead = NULL;}else{SListNode* tmp = pHead;pHead = pHead->next;free(tmp);}}void DestoryList(SListNode*& pHead) //清空整个链表{SListNode* cur = pHead;while (cur){SListNode* tmp = cur;cur = cur->next;free(tmp);}pHead = NULL;}int GetSize(SListNode* pHead) //获取链表长度{assert(pHead);SListNode* cur = pHead;int count = 0;while (cur){count++;cur = cur->next;}return count;}SListNode* Find(SListNode* pHead, DataType x) //查找节点{SListNode* cur = pHead;while (cur){if (cur->data == x)return cur;}cur = cur->next;}return NULL;}void Insert(SListNode* pos, DataType x) // 某位置后插⼊节点{assert(pos);SListNode* tmp = _BuyNode(x);tmp->next = pos->next;pos->next = tmp;}void Erase(SListNode*& pHead, SListNode* pos) //删除某位置的节点{assert(pos);assert(pHead);//pos为头结点if (pHead == pos){pHead = pHead->next;free(pos);return;}////SListNode* prev = pHead;while (prev){if (prev->next == pos){prev->next = pos->next;free(pos);break;}prev = prev->next;}}void DelNonTailNode(SListNode* pos) //// 删除⼀个⽆头单链表的⾮尾节点{assert(pos);assert(pos->next);SListNode* del = pos->next;SListNode* dnext = del->next;pos->data = del->data;pos->next = dnext;free(del);}void InsertFrontNode(SListNode* pos, DataType x) // 在⽆头单链表的⼀个⾮头节点前插⼊⼀个节点{assert(pos);SListNode* tmp = _BuyNode(pos->data);tmp->next = pos->next;pos->next = tmp;pos->data = x;}void Sort(SListNode* pHead) //冒泡排序{assert(pHead);int size = GetSize(pHead);for (int i = 0; i < size - 1; i++){SListNode* left = pHead;SListNode* right = pHead->next;for (int j = 0; j < size - i - 1; j++){if (left->data>right->data){int tmp = left->data;left->data = right->data;right->data = tmp;}right = right->next;left = left->next;}}SListNode* FindMidNode(SListNode* pHead) //查找中间节点{SListNode* fast = pHead;SListNode* slow = pHead;while (fast&&fast->next){slow = slow->next;fast = fast->next->next;}return slow;}SListNode* FindKNode(SListNode* pHead, int k) //查找倒数第k个节点{SListNode* fast = pHead;SListNode* slow = pHead;while (fast && k--){fast = fast->next;}if (k > 0){return NULL;}while (fast){slow = slow->next;fast = fast->next;}return slow;}void PrintTailToHead(SListNode* pHead) //倒着打印单链表(递归){if (pHead){PrintTailToHead(pHead->next);printf("%d ", pHead->data);}}//SListNode* Reverse_(SListNode* pHead) //逆置单链表(需要接收返回值)原链表会被改//{// SListNode* cur = pHead;// SListNode* newHead = NULL;// while (cur)// {// SListNode* tmp = cur;// cur = cur->next;// tmp->next = newHead;// newHead = tmp;// }// return newHead;//}void Reverse(SListNode*& pHead) //逆置单链表(⽆需返回值){SListNode* cur = pHead;SListNode* newHead = NULL;while (cur){SListNode* tmp = cur;cur = cur->next;tmp->next = newHead;newHead = tmp;}pHead = newHead;//return newHead;}SListNode* Merge(SListNode* pHead1, SListNode* pHead2) //合并两个有序链表(合并后依然有序)递归{if (pHead1 == NULL)return pHead2;else if (pHead2 == NULL)return pHead1;SListNode* pMergedHead = NULL;if (pHead1->data < pHead2->data){pMergedHead = pHead1;pMergedHead->next = Merge(pHead1->next, pHead2); }else{pMergedHead = pHead2;pMergedHead->next = Merge(pHead1, pHead2->next); }return pMergedHead;}Test.cpp#include "SList.h"#include<stdlib.h>//测试⽤例void Test1(){// 尾插打印尾删头插头删清空链表SListNode* list = NULL;PushBack(list, 1);PushBack(list, 2);PushBack(list, 3);PushBack(list, 4);PrintSlist(list);PopBack(list);PrintSlist(list);PushFront(list,0);PrintSlist(list);PopFront(list);PrintSlist(list);DestoryList(list);PrintSlist(list);}void Test2(){// 查找节点在某位置插⼊节点删除某位置节点SListNode* list = NULL;PushBack(list, 1);PushBack(list, 2);PushBack(list, 3);PushBack(list, 4);PrintSlist(list);SListNode* pos = Find(list, 2);Insert(pos, 0);PrintSlist(list);Erase(list, Find(list, 0));PrintSlist(list);}void Test3(){SListNode* list = NULL;PushBack(list, 1);PushBack(list, 2);PushBack(list, 3);PushBack(list, 4);PushBack(list, 5);PushBack(list, 6);PrintSlist(list);// 删除⼀个⽆头单链表的⾮尾节点/*SListNode* pos = Find(list, 2);DelNonTailNode(pos);PrintSlist(list);*/// 在⽆头单链表的⼀个⾮头节点前插⼊⼀个节点/*SListNode* pos = Find(list, 2);InsertFrontNode(pos, 0);PrintSlist(list);*///查找中间节点//PrintSlist(FindMidNode(list));//查找倒数第k个节点//SListNode* ret = FindKNode(list, 2);//PrintSlist(ret);//倒着打印单链表(递归)//PrintTailToHead(list);//逆置单链表//SListNode* ret = Reverse(list);//PrintSlist(ret);//PrintSlist(Reverse_(list));//PrintSlist(list);}void Test4(){ //合并两个有序链表(合并后依然有序) SListNode* list = NULL;PushBack(list, 4);PushBack(list, 2);PushBack(list, 1);PushBack(list, 4);PrintSlist(list);Sort(list);PrintSlist(list);/*SListNode* list1 = NULL;PushBack(list1, 2);PushBack(list1, 3);PushBack(list1, 3);PushBack(list1, 0);PrintSlist(list);Sort(list1);PrintSlist(list1);SListNode* ret = Merge(list, list1);PrintSlist(ret);PrintSlist(list);PrintSlist(list1);*/}int main(){//Test1();//Test2();//Test3();Test4();system("pause");return0;}。

单链表基本操作的实现

单链表基本操作的实现单链表是一种常见的数据结构,它由多个节点组合而成,每个节点包含一个数据元素和一个指向下一个节点的指针。

通过指针,我们可以方便地在单链表中进行插入、删除和遍历等操作。

以下是关于单链表基本操作的实现。

1. 单链表的创建单链表的创建需要定义一个空的头结点,它的作用是方便在链表的头部进行添加和删除节点操作。

一个空的头节点可以在链表初始化的过程中进行创建。

```typedef struct Node{int data;struct Node *next;}Node;Node *createList(){Node *head = (Node*)malloc(sizeof(Node)); //创建空的头节点head->next = NULL;return head; //返回头节点的地址}```2. 单链表的插入单链表的插入可以分为在链表头部插入、在链表尾部插入和在链表中间插入三种情况。

a. 在链表头部插入节点:```void insertAtHead(Node *head, int data){Node *node = (Node*)malloc(sizeof(Node));node->data = data;node->next = head->next;head->next = node;}```b. 在链表尾部插入节点:```void insertAtTail(Node *head, int data){Node *node = (Node*)malloc(sizeof(Node));node->data = data;node->next = NULL;Node *p = head;while(p->next != NULL){p = p->next;}p->next = node;}```c. 在链表中间插入节点:```void insertAtMid(Node *head, int data, int pos){ Node *node = (Node*)malloc(sizeof(Node)); node->data = data;node->next = NULL;Node *p = head;int count = 0;while(p->next != NULL && count < pos-1){ p = p->next;count++;}if(count == pos-1){node->next = p->next;p->next = node;}else{printf("插入位置错误!");}}```3. 单链表的删除单链表的删除可以分为在链表头部删除、在链表尾部删除和在链表中间删除三种情况。

C语言实现单向链表及其各种排序(含快排,选择,插入,冒泡)

C语⾔实现单向链表及其各种排序(含快排,选择,插⼊,冒泡) #include<stdio.h>#include<malloc.h>#define LEN sizeof(struct Student)struct Student //结构体声明{long num;int score;struct Student* next;};int n;struct Student* creat() //创建单向链表{struct Student *head=NULL, *p_before, *p_later;p_before = p_later = (struct Student*) malloc(LEN);scanf_s("%ld%d", &p_before->num, &p_before->score);while (p_before->num!=0){n++;if (n == 1) head = p_before;else p_later->next = p_before;p_later = p_before;p_before = (struct Student*) malloc(LEN);scanf_s("%ld%d", &p_before->num, &p_before->score);}p_later->next = NULL;free(p_before);return head;}struct Student* sort(struct Student* list) //冒泡排序,当初写的是内容交换⽽不是指针交换,我知道这不是好的做法,但⽇⼦⼀久,当下没时间和热情改了,⼤家原谅,{ //等有时间了⼀定改struct Student *p, *q;int temp1,i;long temp2;for (p = list, i =1; i < n;i++,p=p->next)for (q = p->next;q!= NULL;q=q->next)if (p->score < q->score){temp1 = p->score;p->score = q->score;q->score = temp1;temp2 = p->num;p->num = q->num;q->num = temp2;}return list;}struct Student* sort1(struct Student* h) //插⼊排序(下边这堆注释是当初写完代码后⼜分析时加的,这⾥必须承认,我参考了⽹上的⼀些代码。

CC++实现单向循环链表(尾指针,带头尾节点)

CC++实现单向循环链表(尾指针,带头尾节点) C语⾔实现单向循环链表,主要功能为空链表创建,链表初始化(头插法,尾插法),链表元素读取,按位置插⼊,(有序链表)按值插⼊,按位置删除,按值删除,清空链表,销毁链表。

单向循环链表和单向链表的区别:(1)单向链表为头指针,循环链表为尾指针,头指针指向头结点,尾指针指向终端结点;(2)为统⼀⽅便操作,单向链表设置头结点,单向循环链表设置头结点和尾结点;(3)设置尾结点后,尾指针指向尾结点,插⼊,删除等操作不⽤移动尾指针。

关键思路:创建头结点和尾结点。

1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node{5int data;6struct Node *next;7 }Node;89//空循环链表创建10//创建头结点和尾结点11//链表尾指针指向尾结点,尾结点指向头结点,头结点指向尾结点12void iniCList(Node **CListTail){13 *CListTail = (Node *)malloc(sizeof(Node));14 Node *CListHead = (Node *)malloc(sizeof(Node));15if (NULL == *CListTail || NULL == CListHead){16 exit(0);17 }1819 (*CListTail)->next = CListHead;20 CListHead->next = *CListTail;21 }2223//循环链表初始化(头插法)24void iniCListHead(Node **CListTail, int n){25//创建头尾结点26 *CListTail = (Node *)malloc(sizeof(Node));27 Node *CListHead = (Node *)malloc(sizeof(Node));28if (NULL == *CListTail || NULL == CListHead){29 exit(0);30 }3132 (*CListTail)->next = CListHead;33 CListHead->next = *CListTail;3435int i = 0;36while (i < n){3738 Node *tmpNode = (Node *)malloc(sizeof(Node));39if (NULL == tmpNode){40 exit(0);41 }42 tmpNode->data = i;43 tmpNode->next = CListHead->next;44 CListHead->next = tmpNode;45 ++i;46 }47 }4849//循环链表初始化(尾插法)50void iniCListTail(Node **CListTail, int n){51//创建头尾结点52 *CListTail = (Node *)malloc(sizeof(Node));53 Node *CListHead = (Node *)malloc(sizeof(Node));54if (NULL == *CListTail || NULL == CListHead){55 exit(0);56 }5758 (*CListTail)->next = CListHead;59 CListHead->next = *CListTail;6061 Node *pCurrent = CListHead;6263int i = 0;64while (i < n){65 Node *tmpNode = (Node *)malloc(sizeof(Node));66if (NULL == tmpNode){67 exit(0);68 }69 tmpNode->data = i;70 tmpNode->next = *CListTail;71 pCurrent->next = tmpNode;72 pCurrent = tmpNode;7374 ++i;75 }76 }7778//循环链表按位置插⼊79void insertCListPos(Node *CList, int pos, int val){ 8081 Node *pCurrent = CList->next; //指向头结点82int i = 1;83while (pCurrent != CList && i < pos){84 pCurrent = pCurrent->next;85 ++i;86 }8788 Node *tmpNode = (Node *)malloc(sizeof(Node)); 89if (NULL == tmpNode){90 exit(0);91 }92 tmpNode->data = val;93 tmpNode->next = pCurrent->next;94 pCurrent->next = tmpNode;9596 }9798//有序循环链表,按值插⼊99void insertCListValue(Node *CList, int val){100 Node *pCur = CList->next->next;101 Node *pPer = CList->next;102103while (pCur != CList && pCur->data < val){ 104 pPer = pCur;105 pCur = pCur->next;106 }107108 Node *tmpNode = (Node *)malloc(sizeof(Node)); 109if (NULL == tmpNode){110 exit(0);111 }112 tmpNode->data = val;113 tmpNode->next = pPer->next;114 pPer->next = tmpNode;115 }116117//循环链表,按位置删除118void deleteCListPos(Node *CList, int pos){119 Node *pCur = CList->next;120121int i = 1;122while (pCur != CList && i < pos){123 pCur = pCur->next;124 ++i;125 }126127 Node *tmpNode = pCur->next;128 pCur->next = tmpNode->next;129free(tmpNode);130 }131132//循环链表,按值删除133//删除空链表为出问题134void deleteCListValue(Node *CList, int val){135 Node *pCur = CList->next->next;136 Node *pPer = CList->next;137138while (pCur != CList && pCur->data != val){ 139 pPer = pCur;140 pCur = pCur->next;141 }142if (pCur == CList)143return;144else{145 pPer->next = pCur->next;146free(pCur);147 }148 }149150//循环链表,清空链表151void claerCList(Node *CList){152 Node *p = CList->next->next;153 Node *q = NULL;154155while (p != CList){ //到达表尾156 q = p->next;157free(p);158 p = q;159 }160161 CList->next = CList; //将头结点指向尾结点162 }163164//循环链表,销毁链表165void destoryCList(Node **CList){166 Node *p = (*CList)->next;167 Node *q = NULL;168169while (p != (*CList)->next){ //到达表头170 q = p->next;171free(p);172 p = q;173 }174175 *CList = NULL;176 }177178//获取元素179void getCList(Node *CList, int pos, int *val){180 Node *pCur = CList->next->next;181int i = 1;182while (pCur != CList && i < pos){183 pCur = pCur->next;184 ++i;185 }186187 *val = pCur->data;188 }189//遍历输出元素190void printCList(Node *CList){191 Node * tmpNode = CList->next->next;192while (tmpNode != CList){ //到达表尾193 printf("%d\n", tmpNode->data);194 tmpNode = tmpNode->next;195 }196 }197198199int main(){200 Node *CList = NULL;201//iniCListHead(&CList, 8);202//iniCList(&CList);203 iniCListTail(&CList, 8);204205//insertCListPos(CList, 1, 2);206//insertCListPos(CList, 2, 4);207//insertCListPos(CList, 3, 6);208//209//insertCListValue(CList, 1);210//211//deleteCListPos(CList, 3);212//213//deleteCListValue(CList, 6);214215//claerCList(CList);216217int a = 0;218 getCList(CList, 2, &a);219 printf("%d\n", a);220221 printCList(CList);222223 printf("%d\n", CList);224 destoryCList(&CList);225 printf("%d\n", CList);226227 system("pause");228return0;229 }C语⾔完整代码 通过C++实现C语⾔的链表,主要区别:(1)struct可以不通过typedef,直接使⽤Node;(2)将malloc和free更换为new和delete1 #include <stdio.h>2 #include <stdlib.h>34struct Node{5int data;6struct Node *next;7 };89//空循环链表创建10//创建头结点和尾结点11//链表尾指针指向尾结点,尾结点指向头结点,头结点指向尾结点 12void iniCList(Node **CListTail){13 *CListTail = new Node;14 Node *CListHead = new Node;1516 (*CListTail)->next = CListHead;17 CListHead->next = *CListTail;18 }1920//循环链表初始化(头插法)21void iniCListHead(Node **CListTail, int n){22//创建头尾结点23 *CListTail = new Node;24 Node *CListHead = new Node;2526 (*CListTail)->next = CListHead;27 CListHead->next = *CListTail;2829int i = 0;30while (i < n){31 Node *tmpNode = new Node;3233 tmpNode->data = i;34 tmpNode->next = CListHead->next;35 CListHead->next = tmpNode;36 ++i;37 }38 }3940//循环链表初始化(尾插法)41void iniCListTail(Node **CListTail, int n){42//创建头尾结点43 *CListTail = new Node;44 Node *CListHead = new Node;4546 (*CListTail)->next = CListHead;47 CListHead->next = *CListTail;4849 Node *pCurrent = CListHead;5051int i = 0;52while (i < n){53 Node *tmpNode = new Node;5455 tmpNode->data = i;56 tmpNode->next = *CListTail;57 pCurrent->next = tmpNode;58 pCurrent = tmpNode;5960 ++i;61 }62 }6364//循环链表按位置插⼊65void insertCListPos(Node *CList, int pos, int val){6667 Node *pCurrent = CList->next; //指向头结点68int i = 1;69while (pCurrent != CList && i < pos){70 pCurrent = pCurrent->next;71 ++i;72 }7374 Node *tmpNode = new Node;7576 tmpNode->data = val;77 tmpNode->next = pCurrent->next;78 pCurrent->next = tmpNode;7980 }8182//有序循环链表,按值插⼊83void insertCListValue(Node *CList, int val){84 Node *pCur = CList->next->next;85 Node *pPer = CList->next;8687while (pCur != CList && pCur->data < val){88 pPer = pCur;89 pCur = pCur->next;90 }9192 Node *tmpNode = new Node;9394 tmpNode->data = val;95 tmpNode->next = pPer->next;96 pPer->next = tmpNode;97 }9899//循环链表,按位置删除100void deleteCListPos(Node *CList, int pos){ 101 Node *pCur = CList->next;102103int i = 1;104while (pCur != CList && i < pos){105 pCur = pCur->next;106 ++i;107 }108109 Node *tmpNode = pCur->next;110 pCur->next = tmpNode->next;111delete tmpNode;112 }113114//循环链表,按值删除115//删除空链表为出问题116void deleteCListValue(Node *CList, int val){ 117 Node *pCur = CList->next->next;118 Node *pPer = CList->next;119120while (pCur != CList && pCur->data != val){ 121 pPer = pCur;122 pCur = pCur->next;123 }124if (pCur == CList)125return;126else{127 pPer->next = pCur->next;128delete pCur;129 }130 }131132//循环链表,清空链表133void claerCList(Node *CList){134 Node *p = CList->next->next;135 Node *q = NULL;136137while (p != CList){ //到达表尾138 q = p->next;139delete p;140 p = q;141 }142143 CList->next = CList; //将头结点指向尾结点144 }145146//循环链表,销毁链表147void destoryCList(Node **CList){148 Node *p = (*CList)->next;149 Node *q = NULL;150151while (p != (*CList)->next){ //到达表头152 q = p->next;153delete p;154 p = q;155 }156157 *CList = NULL;158 }159160//获取元素161void getCList(Node *CList, int pos, int *val){ 162 Node *pCur = CList->next->next;163int i = 1;164while (pCur != CList && i < pos){165 pCur = pCur->next;166 ++i;167 }168169 *val = pCur->data;170 }171//遍历输出元素172void printCList(Node *CList){173 Node * tmpNode = CList->next->next;174while (tmpNode != CList){ //到达表尾175 printf("%d\n", tmpNode->data);176 tmpNode = tmpNode->next;177 }178 }179180181int main(){182 Node *CList = NULL;183//iniCListHead(&CList, 8);184//iniCList(&CList);185 iniCListTail(&CList, 8);186187//insertCListPos(CList, 1, 2);188//insertCListPos(CList, 2, 4);189//insertCListPos(CList, 3, 6);190//191//insertCListValue(CList, 1);192//193//deleteCListPos(CList, 3);194//195//deleteCListValue(CList, 6);196197//claerCList(CList);198199int a = 0;200 getCList(CList, 2, &a);201 printf("%d\n", a);202203 printCList(CList);204205 printf("%d\n", CList);206 destoryCList(&CList);207 printf("%d\n", CList);208209 system("pause");210return0;211 }C++完整代码单向循环链表 注意:(1)单向循环链表销毁时,需要将头结点和尾结点删除;(2)单向循环链表插⼊,删除,遍历,清空链表时,条件从头结点或第⼀节点始,判断指针是否达到尾结点;(3)清空链表时,最后将头结点指向尾结点;(4)销毁链表时,条件从头结点始,判断条件为指针是否到达头结点,最后将指针置空。

数据结构C语言版 线性表的单链表存储结构表示和实现

#include 〈stdio.h>#include <malloc。

h>#include 〈stdlib.h>/*数据结构C语言版线性表的单链表存储结构表示和实现P28—31编译环境:Dev-C++ 4。

9。

9。

2日期:2011年2月10日*/typedef int ElemType;// 线性表的单链表存储结构typedef struct LNode{ElemType data; //数据域struct LNode *next;//指针域}LNode, *LinkList;// typedef struct LNode *LinkList;// 另一种定义LinkList的方法// 构造一个空的线性表Lint InitList(LinkList *L){/*产生头结点L,并使L指向此头结点,头节点的数据域为空,不放数据的。

void *malloc(size_t)这里对返回值进行强制类型转换了,返回值是指向空类型的指针类型.*/(*L)= (LinkList)malloc(sizeof(struct LNode) );if( !(*L))exit(0);// 存储分配失败(*L)-〉next = NULL;// 指针域为空return 1;}// 销毁线性表L,将包括头结点在内的所有元素释放其存储空间。

int DestroyList(LinkList *L){LinkList q;// 由于单链表的每一个元素是单独分配的,所以要一个一个的进行释放while(*L ){q = (*L)—〉next;free(*L );//释放*L = q;}return 1;}/*将L重置为空表,即将链表中除头结点外的所有元素释放其存储空间,但是将头结点指针域置空,这和销毁有区别哦。

不改变L,所以不需要用指针。

*/int ClearList( LinkList L ){LinkList p,q;p = L—〉next;// p指向第一个结点while( p ) // 没到表尾则继续循环{q = p—>next;free( p );//释放空间p = q;}L—>next = NULL; // 头结点指针域为空,链表成了一个空表return 1;}// 若L为空表(根据头结点L—〉next来判断,为空则是空表),则返回1,// 否则返回0.int ListEmpty(LinkList L){if(L—>next ) // 非空return 0;elsereturn 1;}// 返回L中数据元素个数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

链表的C语言实现之单链表的实现/article/2779.html一、单链表的建立有了动态内存分配的基础,要实现链表就不难了。

所谓链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。

链表又分为单链表、双向链表和循环链表等。

我们先讲讲单链表。

所谓单链表,是指数据接点是单向排列的。

一个单链表结点,其结构类型分为两部分:1、数据域:用来存储本身数据2、链域或称为指针域:用来存储下一个结点地址或者说指向其直接后继的指针。

例:typedef struct node{char name[20];struct node *link;}stud;这样就定义了一个单链表的结构,其中char name[20]是一个用来存储姓名的字符型数组,指针*link是一个用来存储其直接后继的指针。

定义好了链表的结构之后,只要在程序运行的时候爱数据域中存储适当的数据,如有后继结点,则把链域指向其直接后继,若没有,则置为NULL。

下面就来看一个建立带表头(若未说明,以下所指链表均带表头)的单链表的完整程序。

#include <stdio.h>#include <malloc.h> /*包含动态内存分配函数的头文件*/#define N 10 /*N为人数*/typedef struct node{char name[20];struct node *link;}stud;stud * creat(int n) /*建立单链表的函数,形参n为人数*/{stud *p,*h,*s; /* *h保存表头结点的指针,*p指向当前结点的前一个结点,*s指向当前结点*/int i; /*计数器*/if((h=(stud *)malloc(sizeof(stud)))==NULL) /*分配空间并检测*/{printf("不能分配内存空间!");exit(0);}h->name[0]='\0'; /*把表头结点的数据域置空*/h->link=NULL; /*把表头结点的链域置空*/p=h; /*p指向表头结点*/for(i=0;i<n;i++){if((s= (stud *) malloc(sizeof(stud)))==NULL) /*分配新存储空间并检测*/{printf("不能分配内存空间!");exit(0);}p->link=s; /*把s的地址赋给p所指向的结点的链域,这样就把p和s所指向的结点连接起来了*/printf("请输入第%d个人的姓名",i+1);scanf("%s",s->name); /*在当前结点s的数据域中存储姓名*/s->link=NULL;p=s;}return(h);}main(){int number; /*保存人数的变量*/stud *head; /*head是保存单链表的表头结点地址的指针*/number=N;head=creat(number); /*把所新建的单链表表头地址赋给head*/}这样就写好了一个可以建立包含N个人姓名的单链表了。

写动态内存分配的程序应注意,请尽量对分配是否成功进行检测。

数据结构学习(C++)之单链表节点类【说明】因为数据结构里用到这个结构的地方太多了,如果用《数据结构》那种声明友元的做法,那声明不知道要比这个类的本身长多少。

不如开放成员,事实上,这种结构只是C中的struct,除了为了方便初始化一下,不需要任何的方法,原书那是画蛇添足。

下面可以看到,链表的public部分没有返回Node或者Node*的函数,所以,别的类不可能用这个开放的接口对链表中的节点操作。

【重要修改】原书的缺省构造函数是这样的Node() : data(NULL), link(NULL) {} 。

我原来也是照着写的,结果当我做扩充时发现这样是不对的。

当Type为结构而不是简单类型(int、……),不能简单赋NULL 值。

这样做使得定义的模板只能用于很少的简单类型。

显然,这里应该调用Type的缺省构造函数。

这也要求,用在这里的类一定要有缺省构造函数。

在下面可以看到构造链表时,使用了这个缺省构造函数。

当然,这里是约定带表头节点的链表,不带头节点的情况请大家自己思考。

【闲话】请不要对int *p = new int(1);这种语法有什么怀疑,实际上int也可以看成一种class。

单链表类定义与实现#ifndef List_H#define List_H#ifndef TURE#define TURE 1#endif#ifndef FALSE#define FALSE 0#endiftypedef int BOOL;#include "Node.h"template <class Type> class List //单链表定义{//基本上无参数的成员函数操作的都是当前节点,即current指的节点//认为表中“第1个节点”是第0个节点,请注意,即表长为1时,最后一个节点是第0个节点public:List() { first = current = last = new Node<Type>; prior = NULL; }~List() { MakeEmpty(); delete first; }void MakeEmpty() //置空表{Node<Type> *q;while (first->link != NULL){q = first->link;first->link = q->link;delete q;}Initialize();}BOOL IsEmpty(){if (first->link == NULL){Initialize();return TURE;}else return FALSE;}int Length() const //计算带表头节点的单链表长度{Node<Type> *p = first->link;int count = 0;while (p != NULL){p = p->link;count++;}return count;}Type *Get()//返回当前节点的数据域的地址{if (current != NULL) return &current->data;else return NULL;}BOOL Put(Type const &value)//改变当前节点的data,使其为value{if (current != NULL){current->data = value;return TURE;}else return FALSE;}Type *GetNext()//返回当前节点的下一个节点的数据域的地址,不改变current{if (current->link != NULL) return &current->link->data;else return NULL;}Type *Next()//移动current到下一个节点,返回节点数据域的地址{if (current != NULL && current->link != NULL){prior = current;current = current->link;return &current->data;}else{return NULL;}}void Insert(const Type &value)//在当前节点的后面插入节点,不改变current{Node<Type> *p = new Node<Type>(value, current->link);current->link = p;}BOOL InsertBefore(const Type &value)//在当前节点的前面插入一节点,不改变current,改变prior {Node<Type> *p = new Node<Type>(value);if (prior != NULL){p->link = current;prior->link = p;prior = p;return TURE;}else return FALSE;}BOOL Locate(int i)//移动current到第i个节点{if (i <= -1) return FALSE;current = first->link;for (int j = 0; current != NULL && j < i; j++, current = current->link)prior = current;if (current != NULL) return TURE;else return FALSE;}void First()//移动current到表头{current = first;prior = NULL;}void End()//移动current到表尾{if (last->link != NULL){for ( ;current->link != NULL; current = current->link)prior = current;last = current;}current = last;}BOOL Find(const Type &value)//移动current到数据等于value的节点{if (IsEmpty()) return FALSE;for (current = first->link, prior = first; current != NULL && current->data != value;current = current->link)prior = current;if (current != NULL) return TURE;else return FALSE;}BOOL Remove()//删除当前节点,current指向下一个节点,如果current在表尾,执行后current = NULL {if (current != NULL && prior != NULL){Node<Type> *p = current;prior->link = p->link;current = p->link;delete p;return TURE;}else return FALSE;}BOOL RemoveAfter()//删除当前节点的下一个节点,不改变current{if (current->link != NULL && current != NULL){Node<Type> *p = current->link;current->link = p->link;delete p;return TURE;}else return FALSE;}friend ostream & operator << (ostream & strm, List<Type> &l){l.First();while (l.current->link != NULL) strm << *l.Next() << " " ;strm << endl;l.First();return strm;}protected:/*主要是为了高效的入队算法所添加的。

相关文档
最新文档