1、本节学习要点:
2、链表的引入:
顺序表和链表的比较:
3、单链表的基本定义:
单链表:每个结点有两部分信息:数据域,存放结点的值(内容);指针域(亦称链域),存放结点后继的地址(或位置)。由于每个结点只有一个链域,故得名单链表。
4、单链表的相关名词:
1.结点:结点=数据域+指针域;
2.空指针:不指向任何结点(常用NULL或^表示)
3.头指针:单链表第一个结点的地址;
1)单链表由头指针唯一确定;
2)头指针具有标识单链表的作用;
3)单链表常用头指针命名,如head表
4.头结点:单链表第一个结点前人为增加的结点,不存放数据;
1)作用:简化链表操作,统一空表与非空表
2)有时可将头结点看成0号结点
5.结点的存储结构
typedef int datatype; //结点数据类型,假设为int
typedef struct node * pointer; //结点指针类型
struct node { //结点结构
datatype data;//数据域
pointer next;//指针域
};
typedef pointer lklist; //单链表类型,即头指针类型
5、单链表的基本运算:
1.建表:头插法、尾插法。
头插法:
lklist creat() { //头插法建表,有头结点
lklist head; pointer s; char ch;
head=new node; //生成头结点
head->next=NULL;
while(cin>>ch,ch!='$') {//输入并检测结束
s=new node; //生成新结点
s−>data=ch; //装入数据
s−>next=head−>next;
head−>next=s; //插到头结点后
}
return head;
}
尾插法:
lklist creat() { //尾插法建表,无头结点的情况
pointer head,rear,s; char ch;
head=NULL; //链表初始值为空
rear=NULL; //尾指针初值也为空
cin>>ch; //读入第一个节点值
while(ch!=’$’) { //检测是否结束
s=new node; s−>data=ch; //生成新结点
if(head==NULL) head=s; //生成第一个节点
else rear->next=s;
rear=s; //尾指针指向新的表位
cin>>ch;
}
if(rear!=NULL) rear−>next=NULL;//尾结点的后继为空
return head;
}<pre name="code" class="cpp">lklist creat() { //尾插法建表,有头结点的情况下
pointer head,rear,s; char ch;
head=new node; //生成头结点
rear=head; //尾指针初值
while(cin>>ch,ch!=’$’) { //读入并检测结束
s=new node; s−>data=ch; //生成新结点
rear−>next=s; rear=s; //插入表尾,改尾指针
}
rear−>next=NULL; //尾结点的后继为空
return head;
}
2.初始化:
lklist initlist() {
pointer head;
head=new node;
head−>next=NULL;
return head;
}
3.求表长:
int length(lklist L) {
int j; pointer p;
j=0; p=L->next; //从首结点开始
while(p!=NULL) { //逐点检测、计数
j++; p=p->next;
}
return j;
4.按序号查找:
pointer get(lklist head, int i) { //0<=i<=n
int j;
pointer p;
if(i==0) return head;//0号结点为头结点
if(i<0) return NULL; //位置非法,无此结点
j=0; //计数器
p=head->next; //从首结点开始搜索
while(p!=NULL) {
j++;if(j==i) break;
p=p−>next; //未到第i个点,继续往后搜索
}
return p; //含找到、未找到两种情况
//未找到时p自动为NULL
}
5.按值查找:
pointer locate(lklist head,datatype x) {
pointer p;
p=head−>next; //从首结点开始搜索
while(p!=NULL) {
if(p−>data==x) break;
p=p−>next; //到下一个点
}
return p; //含找到、未找到两种情况
}
6.插入:
int insert(lklist head,datatype x,int i){
pointer q,s;
q=get(head,i−1); //找第i−1个点
if(q==NULL) //无第i−1点,即i<1或i>n+1时
{cout<<”非法插入位置!\n”;return 0;}
s=new node; //生成新结点
s−>data=x;
s−>next=q−>next; //新结点的后继是原第i个点
q−>next=s; //原第i−1个点的后继是新结点
return 1; //插入成功
}
等效插入:
int insert(lklist head,datatype x,int i){
pointer p,s;
p=get(head,i−1); //找第i−1个点
if(p==NULL) //无第i−1点,即i<1或i>n+1时
{cout<<”非法插入位置!\n”;return 0;}
s=new node; //生成新结点
s−>data=p−>data;
s−>next=p−>next;
p−>data=x;
p−>next=s;
return 1; //插入成功
}
7.删除:
int delete(lklist head,int i) {
pointer p,q;
q=get(head,i−1); //找待删点的直接前趋
if(q==NULL || q−>next==NULL){ //即i<1或i>n时
cout<<”非法删除位置!\n”;
return 0;
}
p=q−>next; //保存待删点地址
q−>next=p−>next; //修改前趋的后继指针
delete p; //释放结点
return 1;
8.销毁:
void destroy(lklist head) { //删除所有结点
pointer p,q;
p=head;
while(p!=NULL) {
q=p->next; //保存待删点后继
delete p; //释放空间
p=q;
}
6、顺序表和单链表的比较:
PS:
1.若线性表需频繁查找却很少进行插入和删除操作,或其操作和元素在表中的位置密切相关时,宜采用顺序表作为存储结构;若线性表需频繁插入和删除时,则宜采用链表做存储结构。
2.当线性表中元素个数变化较大或者未知时,最好使用链表实现;而如果用户事先知道线性表的大致长度,使用顺序表的空间效率会更高
如果有错误请大家指出,共同学习共同进步!更多百度百科