每一个节点包括一个数据域一个指针域,节点在内存中地址能够不连续,可是节点内部地址必然连续。node
typedef struct Lnode{ int data; struct Lnode *next; }Lnode,*LinkList;
1)头插法算法
//头插法创建带头结点的单链表 LinkList create1(LinkList &L){ Lnode *s; int x; L=(LinkList) malloc( sizeof(Lnode));//建立头结点 L->next = NULL; //初始化 printf("往链表中添加数据,99999结束\n"); scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 s->data = x; s->next = L->next; L->next = s; scanf("%d",&x); } return L; }
2)尾插法函数
//尾插法创建单链表 LinkList create2(LinkList &L){ int x; L=(LinkList) malloc( sizeof(Lnode));//建立尾结点 Lnode *s,*r = L;//S为插入节点指针,r为尾指针 printf("往链表中添加数据,99999结束\n"); //scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 scanf("%d",&x); s->data = x; r->next = s; r = s; //r指向新的表尾 } r->next = NULL;//尾节点指针置空 return L; }
1)按值查找spa
//按值查找表节点,返回节点位序,查找失败返回-1 int locateElem(LinkList L, int e){ Lnode *P = L->next; int j=1; while (P!=NULL&&P->data!=e){ P = P->next; j++; } if(P->next == NULL && P->data == e) return j; else if(P->next != NULL && P->data == e) return j; else return -1; } //按值查找表节点,返回节点指针,这是方便链表运算实现 Lnode *locateElem2(LinkList L, int e){ Lnode *P = L->next; while (P!=NULL&&P->data!=e){ P = P->next; } return P;//失败则返回空指针 }
2)按序号查找指针
//按序号查找表节点,返回节点值 int getElem(LinkList L,int i){ int j = 1; Lnode *P = L->next; if(i==0) return 0;//若是i=0,则返回头结点的值,但头结点不存值故返回0 if(i<0) return -1;//错误序号则返回-1 while(P&&j<i)//P非空 { P= P->next; j++; } return P->data; } //按序号查找表节点,返回节点指针,这是方便链表运算实现 Lnode *getElem1(LinkList L, int i){ int j = 1; Lnode *P = L->next; if(i==0) return L;//若是i=0,则返回头结点 if(i<0) return NULL;//错误序号则返回NULL while(P&&j<i)//P非空 { P= P->next; j++; } return P; }
int getLength(LinkList L){ int count = 0; while(L->next->next!=NULL)//此处指针因人而异,思想就是尾节点指针为空结束循环 { L = L->next; count ++; } return count; }
//插入节点算法1(后插,前插通常不考虑) //指定位置插入节点 int insertElem1(LinkList L,int i,int e){ if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i-1);//获取插入位置前驱 s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 s->data = e; s->next = p->next;//此句和下面那句代码不可颠倒,单链表只可找到后继,因此后继指针不能被先覆盖 p->next = s; return 1; } } //插入节点算法2 //只交换数据,不改变指针,在已知节点位置的基础上这个是最优算法 int insertElem2(LinkList L,int i,int e){ int temp; if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i);//获取插入位置前驱 s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 s->data = e; s->next = p->next; p ->next = s; temp = p->data;//这里作个数据交换 p->data = s->data; s->data = temp; return 1; } }
#include <stdio.h> #include <stdlib.h>//malloc函数头文件 //单链表定义 typedef struct Lnode{ int data; struct Lnode *next; }Lnode,*LinkList; //头插法创建带头结点的单链表 LinkList create1(LinkList &L){ Lnode *s; int x; L=(LinkList) malloc( sizeof(Lnode));//建立头结点 L->next = NULL; //初始化 printf("往链表中添加数据,99999结束\n"); scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 s->data = x; s->next = L->next; L->next = s; scanf("%d",&x); } return L; } //尾插法创建单链表 LinkList create2(LinkList &L){ int x; L=(LinkList) malloc( sizeof(Lnode));//建立尾结点 Lnode *s,*r = L;//S为插入节点指针,r为尾指针 printf("往链表中添加数据,99999结束\n"); //scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 scanf("%d",&x); s->data = x; r->next = s; r = s; //r指向新的表尾 } r->next = NULL;//尾节点指针置空 return L; } //求单链表表长 int getLength(LinkList L){ int count = 0; while(L->next->next!=NULL) { L = L->next; count ++; } return count; } //按序号查找表节点,返回节点值 int getElem(LinkList L,int i){ int j = 1; Lnode *P = L->next; if(i==0) return 0;//若是i=0,则返回头结点的值,但头结点不存值故返回0 if(i<0) return -1;//错误序号则返回-1 while(P&&j<i)//P非空 { P= P->next; j++; } return P->data; } //按序号查找表节点,返回节点指针,这是方便链表运算实现 Lnode *getElem1(LinkList L, int i){ int j = 1; Lnode *P = L->next; if(i==0) return L;//若是i=0,则返回头结点 if(i<0) return NULL;//错误序号则返回NULL while(P&&j<i)//P非空 { P= P->next; j++; } return P; } //按值查找表节点,返回节点位序,查找失败返回-1 int locateElem(LinkList L, int e){ Lnode *P = L->next; int j=1; while (P!=NULL&&P->data!=e){ P = P->next; j++; } if(P->next == NULL && P->data == e) return j; else if(P->next != NULL && P->data == e) return j; else return -1; } //按值查找表节点,返回节点指针,这是方便链表运算实现 Lnode *locateElem2(LinkList L, int e){ Lnode *P = L->next; while (P!=NULL&&P->data!=e){ P = P->next; } return P;//失败则返回空指针 } //插入节点算法1(后插,前插通常不考虑) //指定位置插入节点 int insertElem1(LinkList L,int i,int e){ if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i-1);//获取插入位置前驱 s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 s->data = e; s->next = p->next;//此句和下面那句代码不可颠倒,单链表只可找到后继,因此后继指针不能被先覆盖 p->next = s; return 1; } } //插入节点算法2 //只交换数据,不改变指针,在已知节点位置的基础上这个是最优算法 int insertElem2(LinkList L,int i,int e){ int temp; if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i);//获取插入位置前驱 s = (Lnode*)malloc(sizeof(Lnode));//建立新节点 s->data = e; s->next = p->next; p ->next = s; temp = p->data;//这里作个数据交换 p->data = s->data; s->data = temp; return 1; } } int main(){ LinkList L,L1; /* create1(L); LinkList temp = L->next; while(temp->next != NULL) { printf("%d ", temp->data); temp = temp->next; } printf("头插法与存数据的顺序相反\n"); */ create2(L1); LinkList temp2 = L1->next; while(temp2 ->next != NULL) { printf("%d ", temp2->data); temp2 = temp2->next; } printf("尾插法与存数据的顺序相同\n"); int length; length = getLength(L1); printf("单链表长度为:%d\n",length); /* printf("输入取值位序\n"); int i; scanf("%d",&i); printf("第%d位值为%d\n",i, getElem(L1,i)); printf("输入查找值\n"); int e; scanf("%d",&e); printf("值为:%d位序为:%d\n",e, locateElem(L1,e)); */ //插入节点算法1 /* int x1,x2; printf("插入节点算法1\n"); printf("插入位置:"); scanf("%d",&x1); printf("插入值:"); scanf("%d",&x2); int desert = insertElem1(L1,x1,x2); if(desert == 1) { printf("插入成功\n"); LinkList temp3 = L1->next; } else { printf("插入失败,位置不合法\n"); } printf("打印链表(插入算法1)\n"); LinkList temp3 = L1->next; while(temp3 ->next != NULL) { printf("%d ", temp3->data); temp3 = temp3->next; } */ //插入节点算法2 int x3,x4; printf("插入节点算法2\n"); printf("插入位置:"); scanf("%d",&x3); printf("插入值:"); scanf("%d",&x4); int desert1 = insertElem2(L1,x3,x4); if(desert1 == 1) { printf("插入成功\n"); LinkList temp4 = L1->next; } else { printf("插入失败,位置不合法\n"); } printf("打印链表(插入算法2)\n"); LinkList temp4 = L1->next; while(temp4 ->next != NULL) { printf("%d ", temp4->data); temp4 = temp4->next; } return 0; }
单链表做为链表中最简单的一种,摆脱了顺序表对空间的束缚,能够很好的支持动态操做。可是其问题也很明显,每一个节点只能找到其直接后继,而找不到其前一节点。在查找时须要从表头开始遍历表,会增长时间复杂度。code