c语言 单链表的实现

链表的相关术语

  • 结点:
    | 数据元素的存储映像。由数据域和指针域两部分组成
  • 数据域:
    | 存储数据元素信息的域称为数据域
  • 指针域:
    | 存储直接后继存储位置的域称为指针域
  • 链表:
    | n个结点由指针链组成一个链表,它是线性表的链式存储映像,称为线性表的链式存储结构
  • 头指针:
    | 头指针是指向链表中第一个结点的指针。若链表设有头结点,则头指针所 | 指结点为线性表的头结点;若链表不设头结点,则头指针所指结点为该线| 性表的首元结点。
  • 头节点:
    | 是在首元结点之前附设的一个结点,其指针域指向首元结点。头结点的数| 据域可以不存储任何信息,也可存储与数据元素类型相同的其他附加信息。
  • 首元结点:
    | 是指链表中存储第一个数据元素a1的结点
  • 单链表、双链表和循环链表:
    | 结点只有一个指针域的链表,称为单链表或线性链表
    | 结点有两个指针域的链表,称为双链表
    | 首尾相接的链表称为循环链表

单链表的定义和实现

定义:

链式存储结构:结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。
线性表的链式表示又称为非顺序映像或链式映像
链表的存储结构示意图有以下两种形式
| 不带头结点
| ​带头结点
常见问题问题

实现:

单链表的表示和实现

//- - - - - 单链表的存储结构- - - - -
typedef struct Lnode{ //声明结点的类型和指向结点的指针类型
	ElemType data;       //结点的数据域
	struct Lnode *next;         //结点的指针域
}LNode,*LinkList;   //LinkList为指向结构体Lnode的指针类型
LNode *p=new LNode;

//初始化
Status InitList_L(LinkList &L){
    L=new LNode;//或L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    return OK;
}

//取值
Status GetElem_L(LinkList L,int i,ElemType &e){  //获取线性表L中的某个数据元素的内容,通过变量e返回
	p=L->next;//P指向第一个结点(首元结点)
	int j=1;    
	while(p&&j<i){
		p=p->next;
		++j;
	}
	if(!p||j>i) return ERROR; //第i个元素不存在
	e=p->data;   //取第i个元素
	return OK;
}

//查找 
LNode *LocateElem(LinkList L,ElemType e){
//在线性表L中查找值为e的数据元素
//找到,则返回L中值为e的数据元素地址,查找失败返回NULL
p=L->next;
while(p&&p->data!=e)
	p=p->next;
	return p;
}

//插入
Status ListInsert_L(LinkList &L,int i,ElemType e){  //在L中第i个元素之前插入数据元素e
	p=L;
	int j=0;
	while(p&&j<i-1){p=p->next;++j;}//寻找第i-1个结点,p指向i-1结点
	if(!p||j>i-1)return ERROR; //i大于表长+1或者小于1,插入位置非法
	LNode *s=new LNode;s->data=e; //生成新结点s,将结点s的数据域置为e
	s->next=p->next;       //将结点s插入L中
	p->next=s;
	return OK;
}

//删除
Status LisDelete_L(LinkList &L,int i,ElemType &e){  //
   p=L;
   int j=0;
   while((p->next)&&(j<i-1)){
   		p=p->next;
   		++j;
   }//寻找第i个结点,p指向其前驱
   if(!(p->next)||j>i-1)return ERROR; //删除位置不合理
   LNode *q=p->next;             //临时保存被删结点的地址以备释放
   p->next=q->next; //改变删除节点前驱结点的指针域
   e=q->data;         //保存删除节点的数据域
   delete q;             //释放删除节点的空间
   return OK;          
}

创建单链表

//头插法
void CreateList_H(LinkList &L,int n){
	L=new LNode;
	L->next=NULL; //先建立一个带头结点的单链表
	for(int i=0;i<n;++i){
		p=new LNode;  //生成新结点p=(LNode*)malloc(sizeof(LNode));
		cin>>p->data;  //输入元素值 scanf(&p->data);
		p->next=L->next;   //插入到表头
		L->next=p;
		}
}
//后插法
void CreateList_R(LinkList &L,int n){//正位序输入n个元素的值,建立带表头结点的单链表L
	L=new LNode;
	L->next=NULL;
	LNode *r=NULL;
	r=L;   //尾指针r指向头结点
	for(int i=0;i<n;++i){
		p=new LNode;
		cin>>p->data;  //生成新结点,输入元素值
		p->next=NULL;
		r->next=p;   //插入到表尾
		r=p;  //r指向新的尾结点
		}
}

头文件和重命名

#include<iostream>
using namespace std;
#include <assert.h>
#include <malloc.h>
#include <stdio.h>

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int SElemType;
typedef int ElemType;

函数调用测试

int main(){
	LinkList L=NULL;
//(1)初始化一个线性表;
	cout<<"初始化成功输出1:"<<InitList_L(L)<<endl;
//(2)创建一个包含n个正整数值的线性表(线性表的长度n和表中元素的值随机输入);
	cout<<"创建一个包含n个正整数值的线性表(线性表的长度n和表中元素的值随机输入),输入n:";
	int n=0;
	cin>>n;
	CreateList_R(L,n);
//(3)将一个数x插在第i个元素前(x和i在程序运行时随机输入);
	cout<<"一个数x插在第i个元素前(x和i在程序运行时随机输入),输入x:";
	int x=0;
	cin>>x;
	cout<<"输入i:";
	int i=0;
	cin>>i;
	ListInsert_L(L,i,x);
//(4)删除第i个元素(i在程序运行时输入),并在删除结束后输出删除元素的值;
	cout<<"删除第i个元素(i在程序运行时输入),并在删除结束后输出删除元素的值,输入i:";
	int e=0;
	i=0;
	cin>>i;
	LisDelete_L(L,i,e); 
	cout<<"删除的元素为:"<<e<<endl; 
//(5)查找指定元素e是否在线性表中存在,若存在返回此元素的位序,否则返回0;
	cout<<"找指定元素e是否在线性表中存在,若存在返回此元素的位序,否则返回0,输入e:";
	e=0;
	cin>>e;
	cout<<"该元素位序为:"<<LocateElem_L(L,e)<<endl; 
	
//(6)查找指定位置元素的值并输出;
	cout<<"查找指定位置元素的值并输出,输入位置i:";
	e=0;
	i=0;
	cin>>i; 
	GetElem_L(L,i,e);
	cout<<"该位置元素为:"<<e<<endl;
	
//(7)输出线性表中所有元素。	
	cout<<"输出当前链表所有元素值:";
	for(int i=1;i<=n;i++){
		GetElem_L(L,i,e);
		cout<<e;
	} 
	return 0;
}

如有错误或者不足欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值