一
步入链表啦,链表在查找方面实在麻烦,需要一次次遍历,不过它在插入和删除方面却很从容,只需要改变它的指针域就可实现,和顺序表各有千秋。
二
1、代码中L始终代表头结点,所以代码中都用其他变量来替代它移动,保证头结点有人保护
2、p->next及p->next->next的遍历的终结位置要注意
三
看到了个快慢指针的问题,就是在不知链表长度的情况下最快找到中间节点
1、通过遍历整个链表获得长度,在通过长度找到中间结点
2、设置两个指针,一个每次移动两位,一个移动一位
快慢指针应用于:判断单链表是否为循环链表,在有序链表中寻找中位数
http://www.cnblogs.com/hxsyl/p/4395794.html
/**
*快慢指针
**/
Status FastAndSlowPt(LinkList L, ElemType *e)
{
LinkList p,s;
p = L;
s = L;
while(p->next != NULL)
{
if(p->next->next != NULL)
{
p = p->next->next;
s = s->next;
}
else
{
p = p->next;
s = s->next;
}
}
*e = s->data;
return OK;
}
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define MAXSIZE 20
#define OK 1
#define ERROR 0
typedef int Status;
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node *next;
}Node;
typedef struct Node *LinkList; //定义链表
//输出数据
Status visit(ElemType e)
{
printf("%d ", e);
return;
}
//输出整个链表
Status ListTraverse(LinkList L)
{
LinkList p;
//切勿写成p=L,这是将p赋值为头结点,而数据从头结点后一个结点开始
p = L->next;
while(p)
{
visit(p->data);
p = p->next;
}
return OK;
}
/**
*初始化链表
**/
Status ListInit(LinkList *L)
{
*L = (LinkList)malloc(sizeof(Node)); //生成头结点
if(!(*L)) //未分配空间
return ERROR;
(*L)->next = NULL; //建立头结点
return OK;
}
/**
*链表插入第i个位置数据操作
**/
Status ListInsert(LinkList *L, int i, ElemType e)
{
int k = 1;
LinkList p,s;
p = *L;
while(p && k<i) //遍历到i-1
{
p = p->next;
k ++;
}
if(!p || k>i)//结点i不存在
return ERROR;
s = (LinkList)malloc(sizeof(Node));//生成新节点,存储e数据
s->data = e;
//一下两句不能颠倒否则会使链表断裂,就是s->next = s;
s->next = p->next;
p->next = s;
return OK;
}
/**
*链表删除第i个位置数据操作
**/
Status ListDelete(LinkList *L, int i, ElemType *e)
{
int k=1;
LinkList p,s;
p = *L;
while(p->next && k<i)
{
p = p->next;
k++;
}
if(!p || k>i)
return ERROR;
s = p->next;
p->next = p->next->next;
// p->next = s->next;
*e = s->data;//将第i位置的数据赋值给*e
free(s);
return OK;
}
/**
*头插法生成链表
**/
Status ListCreHead(LinkList *L, int i)
{
LinkList p;
int k;
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;//同链表初始化操作,建立头结点
for(k=0; k<i; k++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = k+1;
//同插入结点操作
p->next = (*L)->next;
(*L)->next = p;
}
return OK;
}
/**
*尾插法生成链表
**/
Status ListCreTail(LinkList *L, int i)
{
LinkList p,r;
int k;
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;//*L要始终指向头结点,作为链表的标志,所以不能移步外地
r = *L;//r替代L作为移动指针
for(k=0; k<i; k++)
{
p=(LinkList)malloc(sizeof(Node));
p->data = k+1;
r->next = p;
r = p;
}
p->next = NULL;
return OK;
}
/**
*整表删除
**/
Status ListAllDelete(LinkList *L)
{
LinkList p, q;
p = (*L)->next;
/**
*从头结点开始删除,若从最后一个结点删除,
*需要遍历到最后且没指向前一个结点的指针
**/
while(p)
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL;
printf("\n删除完毕!");
return OK;
}
int main(void)
{
LinkList L, S;
ElemType e;
ListCreHead(&L, 6);
printf("头插法:");
ListTraverse(L);
// ListCreTail(&S, 6);
// printf("\n尾插法:");
// ListTraverse(S);
// ListAllDelete(&S);
// ListInsert(&L, 4, 123);
// ListTraverse(L);
printf("\n删除操作后:");
ListDelete(&L, 4, &e);
ListTraverse(L);
return 0;
}