//单链表 //头指针 //1.头指针是指向链表的第一个节点的指针,若链表有头节点 //则是指向头节点的指针 //2.头指针具有标识作用,所以常用头指针冠以链表的名字 //3.无论链表是否为空,头指针均不为空,头指针是链表的必要元素 //头节点 /* *头节点是为了操作的统一和方便而设立的,放在第一元素的节点之前,其数据域一般无意义 *有了头节点,对于在第一元素节点前插入结点或者删除第一节点就变得与其他元素一样了 *头节点不一定是链表的必要元素 */ /*线性表的单链表定义*/ typedef struct node { elmentaye date; struct node *next;//c语言写法,要用自己来定义节点 } node; typedef struct node *linklist//定义一个指向结点的指针 /* 1.假设p是指向线性表第i个元素的指针,则节点a[i]的数据域可以用p->date来表示; 2.a[i]节点的指针域可以用p->next来表示,p->next是一个指针,指向下一个节点,p->next->data = a[i+1]; 3. */ //获得链表第i个数据的算法思路 /* 1.声明一个结点p指向链表的第一个结点,j从1开始 2.当j小于i时就让p指针向后移动,不断指向下一节点,j累加1 3.若链表尾p为空,就说明这个i元素不存在 .到了末尾还没有找到i,说明i不存在 4.若查找成功,就返回结点p的数据 */ //初始条件l已存在,且1<=i<=list_length //用e返回l中的第i个元素 int getelem(node l,int i, elemtype &e) { int j; linklist p;//声明一个指向结点的指针 p = l->next;//让p指向链表l的第一个结点 j=1; while(P&&j<i)//p不为空或者计数器j还没有等于i { p = p->next; ++j; } if(!p&&j>i)//如果结点为空或者j>i { return 0; } e = p->date; return 1; } //单链表第i个数据插入结点的算法思路 /* 1.声明一结点p,指向链表第一个结点,初始化j从1开始 2.当j<i时,就遍历链表,让p的指针向后移动,不断指向下一节点 3.若到链表末尾p为空,就说明第i个元素不存在 4.若查找成功在系统中生成一个空结点s; 5.将数据元素e赋给s->date; 6.单链表插入标准语句:s->next = p->next; p->next = s; 7.返回成功 */ int linklist(linklist l,int i,enemtype e) { int j; linklist p, s; p = l;//p指向头节点 j =1; while(p&&j<i)//p有定义并且j<i { p = p ->next; ++j; } if(!p||j>i) { return 0;//第i和结点不存在 } s = (linklist)malloc(sizeof(node));//生成新结点 s->date = e; s->next = p->next;//这两句不可颠倒 p->next =s; return 1; } 单链表第i个数据删除结点的算法思路: /* 1.声明一个p指向链表的第一个结点,初始化j从1开始 2.当j小于i时就遍历链表,让P的指针向后移动, 不断指向下一个结点,j累加 3.若到链表末尾p为空,就说明第i个元素不存在 4.若查找成功,将欲删除结点p->next赋值给q; 5.单链表删除的标准语句:p->next = q ->next(p->next->next); 6.将q结点中的数据赋给e作为返回 7.释放q结点 */ int listdelete(linklist l,int i, enemtype &e) { int j; linklist p,q; p=l;//p指向链表头 j=1; while(p->next&&j<i) { p=p->next; ++j; } if(!(p->next)||j>i) return 0;//第i个元素不存在 q= p->next; p->next = q->next;//p指向下下个结点 e = q ->date; free(q); }