C/C++语言数据结构快速入门(代码解析+内容解析)链表(单链表,双链表,循环链表,静态链表)
Posted 蓝盒子bluebox
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++语言数据结构快速入门(代码解析+内容解析)链表(单链表,双链表,循环链表,静态链表)相关的知识,希望对你有一定的参考价值。
一、单链表
1、链表(链式存储)相关概念
(1)什么是单链表
(2)用代码定义一个单链表
(3)用代码定义一个单链表
头插法建立单链表的算法如下:
LinkList * GetElem(LinkList L,int i){
LNode *s;int x;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
scanf("%d",&x);
while(x != 9999){
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
强调一点这是一个单链表 --使用LinkList
强调这是一个结点 --使用LNode *
(4)不带头结点的单链表
(5)带头结点的单链表
(6)不带头结点VS带头结点
2、单链表的插入和删除
(1)按位序插入(带头结点)
ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e
头结点是第0个结点(不存储数据)
a、第一种情况:i的值等于1(最好的情况)
#include<stdio.h>
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
//在第i个位置插入元素e(带头结点)
bool ListInsert(LinkList &L,int i,ElemType e){
if(i < 1)
return false;
LNode *p; //指向p指向当前扫描的结点
int j = 0;//当前p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存储数据)
while(p != NULL && j < i - 1){ //循环找到第i-1个结点
p = p -> next;
j++;
}
if(p==NULL) //i值不合法
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s; //将结点s连接到p之后
return true; //插入成功
}
b、第二种情况:i的值等于3
c、第三种情况:i的值等于5(最坏的情况)
d、第三种情况:i的值等于6
3、按位序插入(不带头结点)
ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。
(1)如果i>1的时候
#include<stdio.h>
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool ListInsert(LinkList &L,int i,ElmeType e){
if(i < 1){
return false;
}
if(i == 1){//插入第1个结点的操作与其他操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next=L;
L = s; //头指针指向新的结点
return true;
}
LNode *p; //指针p指向当前扫描的结点
int j = 1;//当前p指向的是第几个结点
p = L;//p指向的是第几个结点
while(p != NULL && j < i-1){ //循环找到第i-1个结点
p = p->next;
j++;
}
if(p==NULL){//i的值不合法
return false;
}
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;//插入成功
}
4、指定结点的后插操作
a、第一种方式
#include<stdio.h>
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool ListInsert(LinkList &L,int i,ElmeType e){
if(i < 1){
return false;
}
LNode *p; //指针p指向当前扫描的结点
int j = 0;//当前p指向的是第几个结点
p = L;//p指向的是第几个结点
while(p != NULL && j < i-1){ //循环找到第i-1个结点
p = p->next;
j++;
}
if(p==NULL){//i的值不合法
return false;
}
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;//插入成功
}
b、第二种方式
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode ,*LinkList;
//后插操作:在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保存元素e
s->next = p->next;
p->next = s; //将结点s连接到p之后
return true;
}
5、指定结点的前插操作
a、第一种:方式需要手动加入一个头结点
//前插操作:在p结点之前插入元素 e
bool InsertPriorNode(LinkList L,LNode *p,ElemType e)
b、第二种将要插入的数据,插入到需要插入的数据的后面,并交换两个结点数据的值
//前插操作:在p结点之前插入元素e
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连接到p之后
s->data=p->data; //将p中的元素复制到s当中
p->data=e; //p中元素覆盖为e
return true;
}
或者按照下面这个情况
//前插操作:在p结点之前插入结点s
bool InsertPriorNode(LNode *p,LNode *s) {
if(p == NULL || s == NULL){
return false;
}
s->next = p->next;
p->next = s; //s连接p之后
ElemType temp = p->data;//交换数据域部分
p->data = s->data;
s->data = temp;
return true;
}
6、按位序删除(带头结点)
ListDelete(&L,i,&e):删除操作。
删除表L中第i个位置的元素,并用e返回删除的值。
(找到第i-1个结点,将其指向第i+1个结点,并释放第i个结点)
使用free函数释放空间
a、第一种情况:如果i=4的情况下
#include<stdio.h>
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool ListDelete(LinkList &L,int i,ElemType &e){
if(i < 1){
return true;
}
LNode *p; //指针p指向当前扫描到的结点
int j = 0; //当前p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL && j <i-1){ //循环找打第i-1个结点
p=p->next;
j++:
}
if(p==NULL){ //i值不合法
return false;
}
if(p->next == NULL){ //第i-1个结点之后已无其他结点
return false;
}
LNode *q = p->next;//领q指向被删除的结点
e = p->next;//用e返回元素的值
p->next = q->next;//将*q结点从链中“断开”
free(q); //释放结点的存储空间
return true; //删除成功
}
(1)删除指定的给定的结点
//删除指定结点p
bool DeleteNode(LNode *p){
if(p==NULL){
return false;
}
LNode *q = p->next; //令q指向*p的后继结点
p->data=p->next->data;//和后继结点交换数据域
p->next=q->next;//将*q结点从链中"断开"
free(q); //释放后继结点的存储空间
return true;
}
(2)如果p是最后的一个结点
7、单链表(按位查找,按值查找)(注意:本节只讨论“带头结点”的情况)
(1)按位查找
a、边界情况:如果i=0
//按位查找,返回第i个元素(带头结点)
LNode * GetElem(LinkList L,int i){
if(i<0){
return NULL;
}
LNode *p;//指针p指向当前扫描的结点
int j = 0;
p = L;//L指向都结点,头结点是第0个结点(不存储数据)
while(p!=NULL && j < i){
p=p->next;
j++;
}
return p;
}
边界情况
(1)如果i=0
b、边界情况:如果i=8
//按位查找,返回第i个元素(带头结点)
LNode * GetElem(LinkList L,int i){
if(i<0){
return NULL;
}
LNode *p;//指针p指向当前扫描的结点
int j = 0;
p = L;//L指向都结点,头结点是第0个结点(不存储数据)
while(p!=NULL && j < i){
p=p->next;
j++;
}
return p;
}
c、普通情况:如果i=3
//按位查找,返回第i个元素(带头结点)
LNode * GetElem(LinkList L,int i){
if(i<0){
return NULL;
}
LNode *p;//指针p指向当前扫描的结点
int j = 0;
p = L;//L指向都结点,头结点是第0个结点(不存储数据)
while(p!=NULL && j < i){//循环找到第i个结点
p=p->next;
j++;
}
return p;
}
(2)封装对上述代码进行封装
(3)按值查找
a、第一种情况:如果e=8
b、第二种情况:e=6
如果没有找到直接返回NULL
平均时间复杂度
(4)求表的长度
8、单链表的建立
(1)尾插法建立单链表
a、直接插入
#include<stdio.h>
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
//初始化一个单链表(带头结点)
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个位置插入元素e(带头结点)
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1)
return false;
LNode *p;//指向p指向当前扫描的结点
int j = 0;
p = L;
while(p!=NULL && j < i-1){
p = p->next;
j++;
}
if(p==NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;//插入成功
}
//尾插法建立单链表
//初始化单链表
//设置变量length记录的链表长度
//While 循环{
// 每次取一个数据元素e;
// ListInsert(L,length+1,e)
// length++;
//}
以上算法进行插入操作
每次都从头开始之后遍历,时间复杂度为O(n^2)
b、实现后插操作(带头结点)
//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p,ElemType e){
if(p == NULL)
return fasle;
LNode *s = (LNode *)malloc(sizeof(LNode)以上是关于C/C++语言数据结构快速入门(代码解析+内容解析)链表(单链表,双链表,循环链表,静态链表)的主要内容,如果未能解决你的问题,请参考以下文章
C/C++语言数据结构快速入门(代码解析+内容解析)栈的应用
C/C++语言数据结构快速入门(代码解析+内容解析)队列的应用