单链表
代码定义
typedef struct LNode
{
?ElemType data; //值域
?struct LNode *next; //定义域
}LNode,*LinkList;
?
//等价于
struct LNode{
? ?ElemType data;
? ?struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode *LinkList;
//要表示一个单链表时,只需要申明一个头指针L,指向单链表的第一个节点
LNode *L //强调这是一个节点
LinkList L ? ==>二者等价 ?//强调这是一个链表
? ?
//初始化
? ?
//不带头节点
bool InitList(LinkList &L){
? ?L=NULL;
? ?return true;
}
?
//带头结点
bool InitList(LinkList &L){
? ?L=(LNode *)malloc(sizeof(LNode)); //分配一个头节点
? ?if(L==NULL) ?//分配失败
? ? ? ?return false;
? ?L->next=NULL: ?//头节点之后暂时没有节点
? ?return true;
}
?
void test(){
? ?LinkList L; //声明一个指向单链表的指针
? ?InitList(L); //初始化
}
单链表的插入与删除
带头节点的单链表插入
//带头节点的单链表插入
/*
在第i个位置进行插入一个数值,首先找到第i-1个节点,然后进行插入操作
*/
?
typedef struct LNode
{
?ElemType data; //值域
?struct LNode *next; //定义域
}LNode,*LinkList;
?
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,ElemType e){
? ?//判断位置是否合理,i>=1
? ?if(i<1)
? ? ? ?return false;
? ?//声明一个指针指向头节点,与头指针一样
? ?LNode *p;
? ?p=L;
? ?//找到第i-1个节点
? ?int j=0; //记录当前位置
? ?while(p!=NULL && j<i-1){
? ? ? ?p-p->next;
? ? ? ?j++;
? }
? ?//if(p==NULL)
? ?// ? return false; //i值不合法
? ?//LNode *s=(LNode *)malloc(sizeof(LNode));
? ?//s->data=e;
? ?//s->next=p->next;
? ?//p->next=s;
? ?//return true;
? ?return InsertNextNode(p,e);
}
?
//平均时间复杂度 ? O(n)
指定节点的后插操作
//指定节点的后插操作
//后插操作,在p节点之后插入元素e
bool InsertNextNode(LNode *p,ElemType e){
? ?if(p==NULL)
? ? ? ?return false;
? ?LNode *s=(LNode *)malloc(sizeof(LNode)); //申请一个节点
? ?if(s==NULL)
? ? ? ?return false; ?//申请失败
? ?s->data=e;
? ?s->next=p->next;
? ?p->next=s;
? ?return true;
}
//时间复杂度 ? O(1)
指定节点的前插操作
//思路:进行后插,交换节点里面的值
bool InsertPriorNode(LNode *p,ElemType e){
? ?if(p==NULL)
? ? ? ?return false;
? ?LNode *s=(LNode *)malloc(sizeof(LNode)); //申请一个节点
? ?if(s==NULL)
? ? ? ?return false; ?//申请失败
? ?//插入节点
? ?s->next=p->next;
? ?p->next=s;
? ?//交换数值
? ?s-data=p->data;
? ?p-data=e;
? ?return true;
}
//时间复杂度 O(1)
带头节点的单链表删除
//按位序删除
bool ListDelete(LinkList &L,int i,ElemType &e){
? ?if(i<1)
? ? ? ?return fasle;
? ?//找到第i-1个节点
? ?LNode *p;
? ?p=L;
? ?int j=0;
? ?while(p!=NULL && j<i-1){
? ? ? ?p=p->next;
? ? ? ?j++;
? }
? ?if(p==NULL)
? ? ? ?return false; //i不合法
? ?LNode *q=p->next;
? ?p->next=q->next;
? ?e=q->data;
? ?free(q);
? ?return true;
}
//平均时间复杂度 O(n)
?
//指定节点的删除
bool DeleteNode(LNode *p,ElemType e){
? ?//由于找前驱节点非常麻烦,所以找到后继节点,交换值,然后释放后继节点
? ?LNode *q=p->next;
? ?e=p->data;
? ?p->data=q->data;
? ?p->next=q->next;
? ?free(q);
? ?return true;
? ?
? ?//时间复杂度 O(1)
? ?
}
单链表的查找
按值查找 LocateElem(L,e)
//按值查找
LNode * LocateElem(LinkList L,ElemType e){
? ?LNode *p;
? ?p=L; //p指向头节点
? ?p=p->next;
? ?while(p!=NULL && p->data!=e){
? ? ? ?p=p->next;
? }
? ?return p;
}
?
//平均时间复杂度 ? O(n)
按位查找 GetElem(L,i)
//按位查找,返回第i个元素(带头结点)
LNode * GetElem(LinkList L,int i){
? ?if(i<0)
? ? ? ?return NULL;
? ?LNode *p; //表示当前扫描到的节点
? ?int j=0; //当前p指向第几个节点
? ?p=L;
? ?while(p!=NULL && j<i){
? ? ? ?p=p->next;
? ? ? ?j++;
? }
? ?return p;
}//时间复杂度 O(n)
单链表长度
//求单链表的长度
int Length(LinkList L){
? ?int len=0; //长度
? ?LNode *p=L;
? ?while(p->next!=NULL){
? ? ? ?p=p->next;
? ? ? ?len++;
? }
? ?return len;
}
//时间复杂度 ? O(n)
单链表的建立
you have many numbers,you should fix it in a LinkList
step 1:初始化一个单链表
step 2:每次取一个数据元素,插入到表头/尾
头插法
//插入表头
//每次对头节点进行后插操作
LinkList List_HeadInsert(LinkList &L){
? ?//建立头节点
? L=(LinkList)malloc(sizeof(LNode));
? ?L->next=NULL;
? ?int x;
? ?scanf("%d",&x);
? ?LNode *s=L; //指针指向头节点
? ?while(x!=9999){
? ? ? //s申请一个新的空间
? ? ?s=(LNode *)malloc(sizeof(LNode));
? ? ? ?s->data=x;
? ? ? ?s->next=L->next;
? ? ? ?L->next=s;
? ? ? ?scanf("%d",&x);
? }
? ?return L;
}
?
//时间复杂度 ? O(n)
尾插法
//尾插法建立单链表,带头结点
//思路:首先建立一张空表,然后建立两个指针r,s都指向头节点,s每次申请一个新节点进行插入,r始终指向尾部
LinkList List_TailInsert(LinkList &L){
? ?L=(LinkList)malloc(sizeof(LNode)); //头节点
? ?LNode *s,*r;
? ?r=s=L; //都指向头节点
? ?int x;
? ?scanf("%d",&x);
? ?while(x!=9999){
? ? ? ?//进行后插
? ? ? ?//s申请一个新的节点
? ? ? ?s=(LNode *)malloc(sizeof(LNode));
? ? ? ?s->data=x;
? ? ? ?r->next=s;
? ? ? ?r=s;
? ? ? ?scanf("%d",&x);
? }
? ?r->next=NULL;
? ?return L;
}
?
//时间复杂度 ? O(n)
|