首先要定义一个单链表,其中typedef关键字是用来给数据类型重命名的。我这里命名为LNode,LinkList,其中LinkList为声明的头指针L。
注意:
在声明函数的时候,LNode与LinkList等价,不一样的是LinkList强调这是链表,LNode强调这是节点。c++
typedef struct LNode {//定义单链表节点类型 int data;//每一个节点存放一个数据元素 struct LNode* next;//指针指向下一个节点 }LNode,*LinkList;
下面是用尾插法建立一个单链表,首先要初始化一个单链表,而后每取一个数据,咱们须要把这个数据插入到表尾:(其中代码中我建立的单链表是带头节点的)
下图中,我为了方便观看每取一次数据我换了一个颜色,并进行了相应的编号区分方便你们经过看图更加全面的理解下面的代码尤为是r->next= s和r=s这两句
值得注意的是:函数
LinkList List_TailInsert(LinkList *L) { int x; //*L = NULL; *L = (LinkList)malloc(sizeof(LNode));//初始化空表 if (L==NULL) {//考虑内存分匹配失败的状况 return 0; } LNode *s,*r = *L;//定义两个指针使他们分别都和头指针指向相同 scanf_s("%d", &x); while (x!=9999) { s = (LNode *)malloc(sizeof(LNode));//给s分配一个新的节点 if (s == NULL) {//考虑内存分匹配失败的状况 return 0; } s->data = x;//把x赋值给新的节点 if (r == NULL) {//考虑内存分匹配失败的状况 return 0; } r->next= s;//让r的下一个指针与s指针指向相同,也就是在r节点后插入s r=s;//永远保持r只想最后一个节点 printf("--------------------"); scanf_s("%d", &x); } if (r == NULL) { return 0; } r->next = NULL; return *L; }
下面就是打印单链表和主函数里的相应调用了:指针
void GetElem(LinkList L) { LNode* p; int j = 0; p = L; while (p!=NULL) { p = p->next; printf("输入的值为:%d,地址为:%p\n", p->data, p); } } int main() { LinkList L; L=List_TailInsert(&L); GetElem(L); }
所有代码:code
#include <stdio.h> #include <stdlib.h> typedef struct LNode { int data; struct LNode* next; }LNode,*LinkList; LinkList List_TailInsert(LinkList *L) { int x; //*L = NULL; *L = (LinkList)malloc(sizeof(LNode)); if (L==NULL) { return 0; } LNode *s,*r = *L; scanf_s("%d", &x); while (x!=9999) { s = (LNode *)malloc(sizeof(LNode)); if (s == NULL) { return 0; } s->data = x; if (r == NULL) { return 0; } r->next= s; r=s; printf("--------------------"); scanf_s("%d", &x); } if (r == NULL) { return 0; } r->next = NULL; return *L; } void GetElem(LinkList L) { LNode* p; int j = 0; p = L; while (p!=NULL) { p = p->next; printf("输入的值为:%d,地址为:%p\n", p->data, p); } } int main() { LinkList L; L=List_TailInsert(&L); GetElem(L); }
结果:
不建立头结点的尾插法建立单链表的方法:
值得注意的是,打印单链表的函数中,不能先让p指针指向p的下一个指针指向的位置,须要先打印再进行此操做blog
#include <stdio.h> #include <stdlib.h> typedef struct LNode { int data; struct LNode* next; }LNode, * LinkList; LinkList List_TailInsert(LinkList* L) { int x; int i = 0; *L = NULL; //*L = (LinkList)malloc(sizeof(LNode)); //if (L == NULL) { //return 0; //} LNode * s, * r = *L; //LNode* s = *L; scanf_s("%d", &x); s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) { return 0; } s->data = x; *L = s;//L指针指向s指针所指向的节点 r = *L;.//r指针指向L指针所指向的节点,这里指向s也是一个道理 printf("^^^^^^^^^^^^^^^"); scanf_s("%d", &x); while (x != 9999)//里面的循环就和有头结点的循环同样了 { s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) { return 0; } s->data = x; if (r == NULL) { return 0; } r->next = s; r = s; printf("--------------------"); scanf_s("%d", &x); } if (r == NULL) { return 0; } r->next = NULL; return *L; } //打印单链表 void GetElem(LinkList L) { LNode* p; int j = 0; p = L; while (p != NULL) { printf("输入的值为:%d,地址为:%p\n", p->data, p); p = p->next; } } int main() { LinkList L; L = List_TailInsert(&L); GetElem(L); }
结果:
图片
首先须要初始化单链表,而后每取一次数据就向表头插一个数据。
值得注意的是,这里的指针L要表示指针L的下一个指针时须要带括号,不然就会报错"表达式必须包含指向结构或联合的指针类型"内存
#include <stdio.h> #include <stdlib.h> typedef struct LNode { int data; struct LNode* next; }LNode, * LinkList; LinkList List_HeadInsert(LinkList* L) { LNode* s; int x; *L = (LinkList)malloc(sizeof(LNode));//建立头结点 (*L)->next = NULL;//初始为空链表 scanf_s("%d", &x); while (x != 9999) { s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) { return 0; } s->data = x; s->next = (*L)->next;//s指针的下一个指针指向l的下一个指针,也就是s指针的下一个指针指向null (*L)->next = s;//l指针的下一个指针指向s指针的所指的方向 printf("--------------------"); scanf_s("%d", &x); } return *L; } void GetElem(LinkList L) { LNode* p; int j = 0; p = L; while (p!=NULL) { p = p->next; printf("输入的值为:%d,地址为:%p\n", p->data, p); } } int main() { LinkList L; L = List_HeadInsert(&L); GetElem(L); }
结果:
由此可看,单链表的数据是逆置的,因此咱们须要考虑单链表逆置io
下图是单链表逆置的图像解析,为了方便更好理解代码,这个思路有点像后插法,咱们须要声明两个指针变量。一个用来引导指针L一个用来寻找后续节点。
代码以下:class
LinkList Reverse(LinkList L) { LNode * p,* r; p = L->next; L->next = NULL;//断链 while (p!=NULL) { r = p->next; p->next = L->next; L->next = p; p = r; } return L; }
综合上述,头插法创建单链表的所有代码为:变量
#include <stdio.h> #include <stdlib.h> typedef struct LNode { int data; struct LNode* next; }LNode, * LinkList; LinkList List_HeadInsert(LinkList* L) { LNode* s; int x; *L = (LinkList)malloc(sizeof(LNode));//建立头结点 (*L)->next = NULL;//初始为空链表 scanf_s("%d", &x); while (x != 9999) { s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) { return 0; } s->data = x; s->next = (*L)->next;//s指针的下一个指针指向l的下一个指针,也就是s指针的下一个指针指向null (*L)->next = s;//l指针的下一个指针指向s指针的所指的方向 printf("--------------------"); scanf_s("%d", &x); } return *L; } void GetElem(LinkList L) { LNode* p; int j = 0; p = L; while (p!=NULL) { p = p->next; printf("输入的值为:%d,地址为:%p\n", p->data, p); } } //单链表逆置 LinkList Reverse(LinkList L) { LNode * p,* r; p = L->next; L->next = NULL;//断链 while (p!=NULL) { r = p->next; p->next = L->next; L->next = p; p = r; } return L; } int main() { LinkList L; L = List_HeadInsert(&L); L = Reverse(L); GetElem(L); }
结果为: