标签:链表 成功 turn 重命名 基本 size highlight node elk
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef int DataType; //使int重命名为DataType
DataType flag = 0; //flag是用来判断神魔时候输入数据结束
typedef struct Lnode{
DataType data; //定义DataType为int ,存储结构为顺序存储
struct Lnode *next;
}Lnode,*LinkList;
/*
1.链表的创建方法 头插法,尾插法
2.链表分类 单链表,循环链表,双向链表
3.默认都建立带头节点的链表 头节点的数据域不定义数据 head要摸为NULL,要摸为第一个结点的地址
4.单链表的创建方法
头插法:数据输入和输出顺序相反
尾插法:数据输入顺序和输出顺序相同
5.基本操作 查找操作是链表的核心 决定着其他各项依赖于查找的方法的性能 插入和删除都依赖于查找操作
单链表默认都创建带头结点的 因为再进行各种操作时 比如求长度,不带头结点的单链表我们要特殊考虑第一个节点是不是空表
而带头结点的就不用考虑第一个节点
1.求带头结点的表长:int length_LinkList1(LinkList head)
2 求不带头结点的表长:int length_LinkList(LinkList head)
//下面方法都是操作默认带头结点的单链表
3.按序号查找操作(返回第i个位置的指针地址):LinkList get_LinkList(LinkList head,int i)
4.按值查找操作(返回第i个位置的指针地址): LinkList locate_LinkList(LinkList head,DataType x)
5.插入结点操作(分为前插节点和后插节点)(在第i个结点之前插入节点x):int insertP_LinkList(LinkList head,int i,DataType x)
6.插入结点操作(分为前插节点和后插节点)(在第i个结点之后插入节点x):int insertT_LinkList(LinkList head,int i,DataType x)
7.删除结点操作(删除第i个结点):int del_LinkList(LinkList head,int i)
8.多节点删除运算(从第i个结点开始连续删除k个结点):delK_LinkList(LinkList head,int i,int k)
*/
//头插法 不带头节点的单链表
LinkList create_LinkList(){
LinkList head;
head=NULL; //创建一个头节点为空的链表
LinkList s;
DataType x;
cout<<"请输入x的值:";
cin>>x;
while(x!=flag){
s=(LinkList)malloc(sizeof(Lnode));
s->data=x;
s->next=head;
head=s;
cin>>x;
}
return head;
}
//不带头结点的显示链表方法
void out_LinkList(LinkList head){
LinkList p=head;
while(p->next!=NULL){
cout<<p->data<<" ";
p=p->next;
}
cout<<p->data;
}
//头插法 带头节点的单链表
LinkList create_LinkList1(){
LinkList p,head;
p->next=NULL; //设p是头节点
//p->data=0; //表示头节点的数据
head=p; //head是一个游标
LinkList s;
DataType x;
cout<<"请输入x的值:";
cin>>x;
while(x!=flag){
s=(LinkList)malloc(sizeof(Lnode));
s->data=x;
s->next=head;
head=s;
cin>>x;
}
return head;
}
//带头结点的显示单链表的方法 不输出头结点的数据域
void out_LinkList1(LinkList head){
LinkList p=head;
while(p->next!=NULL){
cout<<p->data<<" ";
p=p->next;
}
}
//尾插法 不带头结点
LinkList create_LinkListR(){
LinkList head,s,p;
head=p=NULL;
cout<<"请输入x的值:";
DataType x;
cin>>x;
while(x!=flag){
s=(LinkList)malloc(sizeof(Lnode));
s->data=x;
if(head==NULL){
//说明原来是空表
p=head=s;
}else{
p->next=s;
p=s;
}
cin>>x;
}
p->next=NULL;
return head; //返回头结点的指针
}
//尾插法 带头结点
LinkList create_LinkListR1(){
LinkList head,p,s;
//head->data=100; 可以给头结点数据域赋值验证
head->next=NULL; //带头节点
p=head;
DataType x;
cout<<"请输入x的值:";
cin>>x;
while(x!=flag){
s=(LinkList)malloc(sizeof(Lnode));
s->data=x;
p->next=s;
p=s;
cin>>x;
}
p->next=NULL;
return head;
}
//求带头结点的单链表的长度 (头节点不算入总长度)
int length_LinkList1(LinkList head){
//设置一个移动指针p和计数器count
LinkList p=head;
int count=0;
while(p->next!=NULL){
p=p->next;
count++;
}
return count;
}
//求不带头结点的单链表的长度 要考虑第一个节点
int length_LinkList(LinkList head){
//设置一个移动的指针和一个计数器
LinkList p=head;
int count=0;
if(p==NULL){
cout<<"单链表为空!"<<endl;
return 0;
}else{
count=1;
while(p->next!=NULL){
p=p->next;
count++;
}
return count;
}
}
// 带头结点的 不需要判断是不是空表
//按序号查找操作 返回i位置的指针地址
LinkList get_LinkList(LinkList head,int i){
//判断i位置链表有没有
LinkList p=head;
int count=0;
//这是一种思想,用循环包裹几种结果,在循环体外判断
while(p->next!=NULL && i>count){
//循环结束只有两种情况,要摸链表到头了没找到,要摸找到了
p=p->next;
count++;
}
if(i==count){ //找到了的情况
return p;
}else{ //到头了的情况
return NULL;
}
}
//按值查找
LinkList locate_LinkList(LinkList head,DataType x){
LinkList p = head;
while(p->next!=NULL){
p=p->next;
if(p->data==x)
return p;
}
return NULL;
}
//前插节点 插入操作依赖于查找操作
//单链表注意事项: 前置插入操作要找到待插入结点的前面一个结点
//如果链表是双向链表就没有这个烦恼了,直接找到位置插入即可
int insertP_LinkList(LinkList head,int i,DataType x){
LinkList p = head; //保护头节点 重点 每个方法里面必须都写
LinkList q = get_LinkList(p,i-1);
LinkList s; //创建待插入节点
s=(LinkList)malloc(sizeof(Lnode));
s->data=x;
if(q!=NULL){ //查找成功 找到了第i-1个结点
s->next=q->next;
q->next=s;
return 0; //插入成功
} else{
//cout<<"第i个结点不存在,不能插入第i个节点之前!"<<endl;
return -1;
}
}
//后插节点
//单链表注意事项: 后置插入操作要找到待插入节点的后一个节点
//如果是双向链表就没有这个烦恼了
int insertT_LinkList(LinkList head,int i,DataType x){
LinkList p = head; //保护现场 从汇编处学到的编程经验
LinkList q = get_LinkList(p,i); //查找后一个节点
LinkList s; //创建待插入节点
s=(LinkList)malloc(sizeof(Lnode));
s->data=x;
if(q==NULL){
cout<<"未找到第i个节点!"<<endl;
return -1;
}
if(q->next==NULL){//当前是最后一个节点
q->next=s;
s->next=NULL;
return 0;
}
if(q->next!=NULL){
s->next=q->next;
q->next=s;
return 0;
}
}
//删除结点 删除第i个结点 要找到第i-1个结点
int del_LinkList(LinkList head,int i){
LinkList p = head;
LinkList q = get_LinkList(p,i-1); //查找第i-1个结点
if(q==NULL || q->next==NULL){ //不存在有两种情况
cout<<"第i个结点不存在!删除失败!"<<endl;
return -1;
} else{ //存在有两种情况
if(q->next->next==NULL){//恰巧要删除的是最后一个结点
free(q->next);
q->next=NULL;
return 0;
}else{ //要删除的结点在链表内部
LinkList s;
s=q->next;
q->next=s->next;
free(s);
return 0;
}
}
}
int main(int argc, char** argv) {
LinkList head = create_LinkListR1();
out_LinkList(head);
cout<<endl;
cout<<length_LinkList1(head)<<endl;
cout<<"插入操作:"<<endl;
int i = insertT_LinkList(head,3,100);
if(i==0){
out_LinkList(head);
}else{
cout<<"插入失败!"<<endl;
}
int j = del_LinkList(head,4);
if(j==0){
out_LinkList(head);
}else{
cout<<"error"<<endl;
}
free(head);
return 0;
}
标签:链表 成功 turn 重命名 基本 size highlight node elk
原文地址:https://www.cnblogs.com/nanfengnan/p/14378630.html