一、链表的概念
1)链式存储结构的特点
- 结点存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。
- 线性表的链式表示又称为非顺序映像或链式映像。
- 链表中元素的逻辑次序和物理次序不一定相同。
存储地址 | 数据域 | 指针域 |
0003 | a | 0005 |
0005 | b | 0012 |
0012 | c | NULL |
2)头指针
指向链表中第一个结点的指针,单链表是由头指针唯一确定的,因此单链表可以用头指针的名字来命名。
例如根据上表:
3)首元结点
是指链表中存储第一个数据元素的结点,如上图的a便是首元结点。
4)头结点
是链表的首元结点之前附设的一个结点。
5)链表
n个结点由指针链组成一个链表。
二、单链表的基本操作
头文件名称:Stlnode.h
#pragma once
#include<iostream>
#include <malloc.h>
typedef int Elemtype;
typedef int status;
using namespace std;
//定义链表节点
typedef struct Lnode {
Elemtype data; //数据域
struct Lnode* next; //指针域
}Lnode, * Linklist; //Linklist是指向结构体Lnode的指针类型
Linklist L; //定义链表L,或者是Lnode*L
//注意:结构体用. 指针用->
//链表的初始化
status Initlist(Linklist &L) { //注意一下&是cpp文件中的引用,表示对L地址的操作。
L= (Linklist)malloc(sizeof(Lnode)); //或者是L=new Lnode;
L->next=NULL;
}
//判断链表是否为空
void ListElem(Linklist L) {
if (L->next) //不为空
cout<<"no";
else
cout<<"yes";
}
//清空链表
void Clearlist(Linklist& L) {
Lnode* p, * q;
p = L->next;
while (p) { //还没到表尾
q = p->next;
delete p;
p = q;
}
L->next = NULL; //头结点指针域为空
cout << "ok";
}
//求单链表的表长
void Listlength(Linklist L) { //返回L中数据元素个数
Linklist p;
p = L->next; //p指向第一个结点
int i = 0;
while (p != NULL) {
i++;
p = p->next;
}
cout<<i;
}
//取值
status Getelem(Linklist L, int i, Elemtype e) {
Lnode *p = L->next;;
int j = 1; //初始化
while (p != NULL && j < i) {
p = p->next;
++j;
} //用指针p进行扫描,直到j==i
if (p == NULL || j > i)
cout << "error"; //第i个元素不存在
p->data=e; //取第i个元素
return e;
}
//查找
void LocateElem(Linklist L, Elemtype e) { //e是我们要查找的数据元素
Lnode* p = L->next;
int i=0;
while (p != NULL && p->data != e) {
p = p->next;
i++;
}
// cout<< p; //返回数据元素的地址
cout<<i;
}
//插入新结点
void ListLnsert_L(Linklist &L,int i,Elemtype e){
Lnode *p,*s;
p=L;
int j=0;
while(p!=NULL&&j<i-1){
p=p->next;
j++;
}//寻找第i-1个结点,p指向i-1
if(!p||j>i-1) {
cout<<"error";
}
s=new Lnode;
s->data=e;
s->next=p->next; //s插入L中
p->next=s;
cout<<"ok";
}
//打印链表
void SlistPrint(Linklist L){
Lnode*p=L;
while(p!=NULL){
cout<<p->data;
cout<<"\n";
p=p->next;
}
}
//删除第i个数据元素
void ListDelect(Linklist &L,int i,Elemtype &e) {
Lnode*p;
int j=0;
p=L;
while(p->next&&j<i-1){
p=p->next;
j++;
}//寻找第i-1个结点
if(!(p->next)&&j>i-1){
cout<<"error";
}
Lnode *q=p->next;
p->next=q->next;
e=q->data; //保存删掉结点的数据域
delete q;
cout<<"ok" ;
}
//前插法创建链表
void CreateList_L(Linklist& L, int n) {
L = new Lnode;
L->next = NULL; //先建立一个带头结点的单链表
for (int i = 0; i < n; ++i) {
Linklist p =(Linklist)malloc(sizeof(Lnode)) ; //生成新结点*p
cin >> p->data;
p->next = L->next; //
L->next = p; //将新结点*p插入头结点之后
}
}
//尾插法
void CreateList_R(Linklist &L,int n){
L=new Lnode;
L->next=NULL;
Lnode*r=L; //尾指针指向头结点
for(int i=0;i<n;i++) {
Lnode*p=new Lnode;
cin>>p->data; //输入元素值
p->next=NULL;
r->next=p; //插入到表尾
r=p; //r指向表尾
}
}
源文件:
#include"Stlnode.h"
int main() {
Linklist L;
Initlist(L);
CreateList_R(L,3);
ListLnsert_L(L,1,67);
cout<<"\n";
Listlength(L);
cout<<"\n";
LocateElem(L, 67);
SlistPrint(L);
return 0;
}
//这里的11670848,其实我有一点弄不懂,我认为是头结点(也就是L)的原因,因为L->data是不知道的(空的),所以系统就随机了一个数。
//可能写的不是很好,请多包涵。
//最近我在看数据库(MySQL),希望有大佬可以带带我。