单链表是线性表的链式存储。一般对于每一个节点都会有一个数据域和一个指针域,指针指向下一个节点的地址,所以在逻辑结构上相邻的节点,物理位置可能不是相邻的。
单链表一般会引入一个头结点用于同一处理空表和非空表。对于链表第一个节点的操作无异于其他节点,操作更加方便。
单链表的创建一般有头插法和尾插法。头插法在链表得头结点后插入,这就使得整个链表得顺序与插入时的顺序相反,尾插法在链表中创建了一个尾结点指针,始终指向链表的尾结点,最终链表的顺序与插入元素的顺序一致。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
using namespace std;
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode ,*LinkList; /*LNode只表示线性表的一个节点,LinkList表示的是
线性表的指针.可以表示整个线性表。就像数组一样 */
int InitList(LinkList &L); //创建一个新的线性表
LinkList ListInsert_Head(LinkList &L,int n); //线性表的头插法插入元素创建链表
LinkList ListInsert_Tail(LinkList &L,int n); //线性表的尾插法插入元素创建链表
LinkList InsertElem(LinkList &L,int k,ElemType &e); //插入元素:在第k个位置插入元素e
LinkList ListDelete(LinkList &L,int k); //删除元素:删除第k个元素操作
int TraveList(LinkList &L); //遍历线性表
int ElemSearch(LinkList &L,ElemType &e); //查找元素
void DestorytList(LinkList &L); //销毁线性表
void ClearList(LinkList &L); //清空线性表
LinkList UnionList(LinkList &La,LinkList &Lb); //连接两个线性表
int main()
{
LinkList Ha;
LinkList Hb;
InitList(Ha);
InitList(Hb);
int a=99;
ListInsert_Head(Ha,10);
TraveList(Ha);
InsertElem(Ha,9,a);
TraveList(Ha);
ListDelete(Ha,6);
TraveList(Ha);
int k=ElemSearch(Ha,a);
cout << k << endl;
//TraveList(Hb);
ListInsert_Tail(Hb,5);
TraveList(Hb);
UnionList(Ha,Hb);
TraveList(Ha);
ClearList(Ha);
TraveList(Ha);
return 0;
}
int InitList(LinkList &L){ //线性表的指针LinkList,&L用来取到地址然后申请内存
L=(LinkList)malloc(sizeof(LNode)); //C申请内存 ,L表示头指针
//L=new LNode; //C++申请内存
L->next=NULL; //L指向了头结点
return OK;
}
LinkList ListInsert_Head(LinkList &L,int n){
LinkList p; //声明一个节点指针,用于存放数据并做插入操作
while(n--){
p=new LNode; //创建该节点的指针
cin >> p->data;
p->next=L->next; //头插法
L->next=p;
}
return L;
}
LinkList ListInsert_Tail(LinkList &L,int n){
LNode *p; //声明一个结点指针,用于存放数据并做插入操作
LinkList r; //声明一个指针表示尾指针
r=L;
while(n--){
p=(LinkList)malloc(sizeof(LNode));
cin >> p->data;
p->next=NULL;
r->next=p; //尾插法,在结尾进行操作
r=p;
}
return L;
}
LinkList InsertElem(LinkList &L,int k,ElemType &e){
LinkList p;
LinkList q;
q=L;
p=(LinkList)malloc(sizeof(LNode));
p->data=e; //生成新节点*p,数据域为e
int j=0;
while(q&&j<k-1){ //因为需要放到第k个位置,所以插到k-1的后面即可
q=q->next;
j++;
}
p->next=q->next;
q->next=p;
return L;
}
LinkList ListDelete(LinkList &L,int k){
int j=0;
LinkList p;
LinkList q;
q=new LNode;
p=new LNode;
p=L;
while(p&&j<k-1){ //指针移到需要删除节点的前一个
p=p->next;
j++;
}
//cout << "++++";
q=p->next;
p->next=p->next->next; //修改删除节点的前驱的指针域
free(q); //释放内存
return L;
}
int TraveList(LinkList &L){
int length=0;
LinkList p;
p=L->next;
while(p!=NULL){
cout << p->data << " " ;
p=p->next;
length++;
}
cout << endl;
cout << "The Length is " << length <<endl;
return length;
}
int ElemSearch(LinkList &L,ElemType &e){
LinkList p;
int k=0;
p=L;
while(p!=NULL){
if(p->data==e){
return k;
}
k++;
p=p->next;
}
if(p==NULL)
return 0;
}
void DestorytList(LinkList &L){
LinkList p;
while(L!=NULL){
p=L;
L=L->next;
free(p);
}
return ;
}
void ClearList(LinkList &L){
LinkList p;
while(L->next){
p=L->next;
L->next=p->next;
free(p);
}
return ;
}
LinkList UnionList(LinkList &La,LinkList &Lb){
LinkList p;
p=La;
while(p->next){
p=p->next;
}
p->next=Lb->next; //这里不能直接指向Lb因为Lb也有一个头结点需要直接跳过
return La;
}
下面是运行结果: