注: 第二章是基础,很重要,从课后习题也可以看出顺序表和链表的重要性,主要是掌握有哪些类型的题目,先理解看懂,再反复练,最后能快速默写出来。
2.2 单链表
单链表节点定义
typedef struct LNode{ //定义单链表结点类型
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList;
单链表基本操作
头插法
LinkList CreateList1(LinkList &L){
//从表尾到表头逆向建立单链表L,每次均在头结点之后插入元素
LNode s;int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
L->next=NULL; //初始化为空链表
while(scanf(“%d”,&x) != EOF){ //循环输入
s=(LNode)malloc(sizeof(LNode));//创建新结点
s->data=x;
s->next=L->next;
L->next=s; //将新结点插入表中,L为头指针
scanf(“%d”,&x);
}//while结束
return L;
}
尾插法
LinkList CreatList2(LinkList &L) {
//从表头到表尾正向建立单链表L,每次均在表尾插入元素
int x; //设元素类型为整型
L = (LinkList)malloc(sizeof(LNode));
LNode *s, r = L; //r为表尾指针
while(scanf(“%d”,&x) != EOF) { //循环输入
s = (LNode)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s; //r指向新的表尾结点
scanf(“%d”,&x);
}
r->next = NULL; //尾结点指针置空
return L;
}
按序号查找
LNode *GetElem(LinkList L,int i){
//本算法取出单链表L(带头结点)中第i个位置的结点指针
int j=1; //计数,初始化为1
LNode *p=L->next; //头结点指针赋给P
if(i==0)
return L; //若i等于0.则返回头结点
if(i<1)
return NULL; //若i无效,则返回NULL
while(p&&j<i){ //从第1个结点开始找,查找第i个结点
p=p->next;
j++;
}
return p; //返回第i个结点的指针,如果i大于表长,p=NULL,直接返回p即可
}
按值查找
LNode *LocateElem(LinkList L,ElemType e){
//本算法查找单链表L(带头结点)中数据域值等于e的结点指针,否则返回NULL
LNode *p=L->next;
while(p!=NULL&&p->data!=e)//从第1个结点开始查找data域为e的结点
p=p->next;
return p; //找到后返回该结点指针,否则返回NULL
}
插入节点操作 (两种)
前插
p=GetElem(L,i-1); //查找插入位置的前驱结点
s->next=p->next; //图2.7中操作步骤1
p->next=s; //图2.7中操作步骤2
后插
//将s结点插入到p之前的主要代码片段
s->next=p->next; //修改指针域,不能颠倒
p->next=s;
temp=p->data; //交换数据域部分
p->data=s->data;
s->data=temp;
删除节点操作
//删除所给节点后一节点
p=GetElem(L,i-1); //查找删除位置的前驱结点
q=p->next; //令q指向被删除结点
p->next=q->next; //将*q结点从链中“断开”
free(q); //释放结点的存储空间
//删除所给节点
q=p->next; //令q指向p的后继结点
p->data=p->next->data; //和后继结点交换数据域
p->next=q->next; //将q结点从链中“断开”
free(q); //释放后继结点的存储空间