数据结构-线性表之单向链表--一点一滴
单向链表
单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。
单向链表的数据结构可以分为两部分:数据域和指针域,数据域存储数据,指针域指向下一个储存节点的地址。分为动态单向链表和静态单向链表。单向链表也可以根据是否带头节点分为带头节点结构和无带头节点结构。我们把指向单链表的指针为头指针。头指针所指的不存放数据元素的第一个节点称作头节点。存放数据元素的节点成为第一个数据元素节点。
注:第一个数据元素节点在带头节点单链表中是第二个节点;而在不带头节点的单链表中是第一个节点。
带头节点单链表和不带头节点单链表比较
拿出来做比较主要是因为带头节点和不带头节点单链表删除和插入操作不一样,只是对于头指针,容易出现错误。废话少说,比较内容如下:
- 如选用带头节点的单链表,设头指针为head,则在第一个数据元素节点前插入元素,不会改变头指针head的值,改变的是头指针所指向头节点的指针域值。即改变的是head->next的值。当临时变量p等同于head时,改变的是指针p->next的值,这与在其他元素节点前插入节点的过程相同;类似的则删除第一个数据元素节点时,不会改变头指针head的值,即改变的是head->next,当临时变量等同于head时,改变的是p->next的值。这与删除其他位置元素节点相同。
- 如选用不带头节点的单链表,设头指针为head,则在第一个数据元素节点前插入元素,头指针head的值将改变为等于s指针的值。(s相当于需要插入的节点元素),若在其他位置插入元素s,头指针head不会改变,改变的是临时变量p->next的值。如删除第一个元素节点时,头指针head的值改变为head->next,删除其他元素节点时,不会改变头指针head的值,改变的是临时变量p->next的值。
如果对于上面的比较有点困惑,你可以画一下原型图。head为头指针,节点s是需要插入的元素节点。p是指向你单链表插入或删除的第n-1个节点。(比如你是在第4个节点前插入,p是指向了第3个节点)。
单链表的节点定义和基本操作
1 /********单链表的定义*******/ 2 typedef struct Node 3 { 4 DataType data; 5 struct Node *next; 6 }SLNode; 7 8 /* 9 * 初始化单链表 10 *在初始化之前头指针参数head没有具体的地址值,在初始化操作时 11 *头指针head才得到具体的了具体的地址值,而这个地址值要返回给 12 *调用函数,所以,此时的头指针参数head要设计成指针的指针类型 13 *如果此时头指针类型设置为指针类型,那么调用方将无法得到在初 14 *使化函数中被赋值的头指针参数head的数值 15 */ 16 17 18 void InitiateList(SLNode **head) 19 { 20 *head = (SLNode *)malloc(sizeof(SLNode)); 21 (*head)->next = NULL; 22 } 23 24 /*得到单链表的元素节点个数*/ 25 int GetListLength(SLNode *head) 26 { 27 SLNode *p = head; 28 int size = 0; 29 while(p->next != NULL) 30 { 31 p=p->next; 32 size ++; 33 } 34 return size; 35 } 36 37 /*在带头节点的单链表head的第i个(0<=i<=size)节点插入一个数据元素为x的节点*/ 38 int InsertListNode(SLNode *head,int i,DataType x) 39 { 40 SLNode *p,*q; 41 p = head; 42 int j = -1; 43 while(p->next != NULL && j<i-1) 44 { 45 p = p->next; 46 j++; 47 } 48 if(j != i-1) 49 { 50 printf("Insert Position is error\n"); 51 return 0; 52 } 53 q = (SLNode *)malloc(sizeof(SLNode)); 54 q->data = x; 55 q->next = p->next; 56 p->next = q; 57 return 1; 58 } 59 60 /*删除带头节点单链表的第i个节点(0<= i<=size-1) 61 * 被删除节点的数据域值由x带回,删除成功返回1失败 62 * 返回0 63 */ 64 65 int DeleteListNode(SLNode *head,int i,DataType *x) 66 { 67 SLNode *p,*q; 68 p = head; 69 int j = -1; 70 while(p->next != NULL && p->next->next != NULL && j<i-1) 71 { 72 p=p->next; 73 j++; 74 } 75 if(j != i-1) 76 { 77 printf("Error\n"); 78 return 0; 79 } 80 q = p->next; 81 *x = q->data; 82 p->next = p->next->next; 83 free(q); 84 return 1; 85 } 86 87 /* 取数据元素*/ 88 int GetListNode(SLNode *head,int i,DataType *x) 89 { 90 SLNode *p; 91 p = head; 92 int j = -1; 93 while(p->next != NULL && j<i) 94 { 95 p=p->next; 96 j++; 97 } 98 if(j != i) 99 { 100 printf("error\n"); 101 return 0; 102 } 103 *x = p->data; 104 return 1; 105 } 106 107 /* 撤销单链表*/ 108 void DestroyList(SLNode **head) 109 { 110 SLNode *p,*q; 111 p = *head; 112 while(p != NULL) 113 { 114 q = p; 115 p = p->next; 116 free(q); 117 } 118 *head = NULL; 119 }
单链表的实例
建立一个单链表,首次输入1,2,3,4,5,6,,7,8,9,10元素节点,然后删除元素5的节点。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 typedef int DataType; 5 #include "SLNode.h" 6 int main(void) 7 { 8 SLNode *head; 9 int i = 0,temp; 10 InitiateList(&head); 11 for(i=0;i<10;i++) 12 { 13 InsertListNode(head,i,i+1); 14 } 15 DeleteListNode(head,4,&temp); 16 printf("It will delete node value is %d\n",temp); 17 for(i=0;i<GetListLength(head);i++) 18 { 19 GetListNode(head,i,&temp); 20 printf("%d\t",temp); 21 } 22 printf("\n"); 23 DestroyList(&head); 24 return 0; 25 }
取法乎上,仅得其中;取法乎中,仅得其下;取法乎下,一无所得。