目录
一.线性表的基本操作
1.&表示C++语言中的引用调用
什么时候要传入参数的引用“&”--对参数的修改结果需要“带回来”
(1)未使用&时的代码
#include <stdio.h>
#include <stdlib.h>
void test(int x){
x=1024;
printf("test函数内部x=%d\n",x);
}
int main()
{
int x=1;
printf("调用test之前x=%d\n",x);
test(x);
printf("调用test之后x=%d\n",x);
return 0;
}
运行结果:
(2)使用&时的代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
void test(int &x){
x=1024;
printf("test函数内部x=%d\n",x);
}
int main()
{
int x=1;
printf("调用test之前x=%d\n",x);
test(x);
printf("调用test之后x=%d\n",x);
return 0;
}
运行效果:
二、顺序表的基本操作
1.顺序表的静态分配
#define MaxSize 10 //定义线性表的最大长度
//ElemType可以是任何类型,如int,double......
typedef struct{
ElemType data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
(1)不进行初始化,会发生内存中会有遗留的“脏数据”
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10 //定义线性表的最大长度
using namespace std;
typedef struct{
int data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
void InitList(SqList &L){
// for(int i=0;i<MaxSize;i++) //将数据初始化
// L.data[i]=0;
L.length=0; //顺序表的初始长度为0
}
int main()
{
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//尝试违规打印整个data数组
for(int i=0;i<MaxSize;i++){
printf("data[%d]=%d\n",i,L.data[i]);
}
return 0;
}
运行结果:
(2)进行初始化
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10 //定义线性表的最大长度
using namespace std;
typedef struct{
int data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
void InitList(SqList &L){
for(int i=0;i<MaxSize;i++) //将数据初始化
L.data[i]=0;
L.length=0; //顺序表的初始长度为0
}
int main()
{
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//尝试违规打印整个data数组
for(int i=0;i<MaxSize;i++){
printf("data[%d]=%d\n",i,L.data[i]);
}
return 0;
}
运行结果:
2.顺序表的动态分配
#define InitSize 10 //定义顺序表的初始长度
//ElemType可以是任何类型,如int,double......
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义(动态分配方式)
(1)key:动态申请和释放内存空间:
C语言---malloc、free函数
//malloc函数返回一个指针,需要强制转型为题目定义的数据元素类型指针
//malloc申请的是一整片连续的存储空间
L.data=(ElemType *)malloc(sizeof(ElemTye)*InitSize);
C++---new、delete关键字
L.data=new ElemType[InitSize];
(2)代码实现:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define InitSize 10 //定义线性表的最大长度
using namespace std;
typedef struct{
int *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义(动态分配方式)
void InitList(SqList &L){
//用malloc函数申请一篇连续的存储空间
//L.data=(int *)malloc(InitSize*sizeof(int));
L.data = new int[InitSize];
L.length=0;
L.MaxSize=InitSize;
}
void IncreaseSize(SqList &L,int len){
int *p=L.data;
//c语言版本
// L.data=(int *)malloc((L.MaxSize+len)*sizeof(int));
// C++版本
L.data = new int[L.MaxSize + len];
for(int i=0;i<L.MaxSize;i++){ //复制原来数组到新的数组
L.data[i]=p[i];
}
L.MaxSize=L.MaxSize+len;
//free(p);
delete[] p; // 释放原来的内存空间
}
int main()
{
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
printf("原来的数组长度%d\n",L.length);
printf("原来的数组最大长度%d\n",L.MaxSize);
IncreaseSize(L,5);
printf("加长后的数组最大长度%d\n",L.MaxSize);
return 0;
}
运行结果:
3.顺序表的插入
(1)代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10 //定义线性表的最大长度
using namespace std;
typedef struct{
int data[MaxSize];//用静态的“数组”存放数据元素
int length;//顺序表的当前长度
}SqList;//顺序表的类型定义
void InitList(SqList &L){
for(int i=0;i<MaxSize;i++) //将数据初始化
L.data[i]=0;
L.length=0; //顺序表的初始长度为0
}
bool ListInsert(SqList &L,int i,int e){//插入操作
if(i<1||i>L.length+1){//输入数据的有效判断
return false;
}
if(L.length>=MaxSize){
return false;
}
for(int j=L.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
int main(){
SqList L;
InitList(L);
for(int i=0;i<5;i++){
L.data[i]=i;
++L.length;
}
printf("原来length%d\n",L.length);
for(int i=0;i<L.length;i++){
printf("%d\t",L.data[i]);
}
printf("\n");
if(ListInsert(L,3,3)){
printf("插入成功!\n");
}else{
printf("输入数据有误\n");
}
printf("后来length%d\n",L.length);
for(int i=0;i<L.length;i++){
printf("%d\t",L.data[i]);
}
printf("\n");
return 0;
}
运行结果:
4.线性表的删除
(1)代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10 //定义线性表的最大长度
using namespace std;
typedef struct{
int data[MaxSize];//用静态的“数组”存放数据元素
int length;//顺序表的当前长度
}SqList;//顺序表的类型定义
void InitList(SqList &L){
for(int i=0;i<MaxSize;i++) //将数据初始化
L.data[i]=0;
L.length=0; //顺序表的初始长度为0
}
bool ListDelete(SqList &L,int i,int &e){//插入操作
if(i<1||i>L.length){//输入数据的有效判断
return false;
}
e=L.data[i-1];//i是数据的位序,i-1是数据的下标
for(int j=i;j<L.length;j++)
L.data[j-1]=L.data[j];
L.length--;
return true;
}
int main(){
SqList L;
InitList(L);
int e=-1;
for(int i=0;i<5;i++){
L.data[i]=i;
++L.length;
}
printf("原来length%d\n",L.length);
for(int i=0;i<L.length;i++){
printf("%d\t",L.data[i]);
}
printf("\n");
if(ListDelete(L,3,e)){
printf("删除成功!\n");
}else{
printf("输入数据有误\n");
}
printf("后来length%d\n",L.length);
for(int i=0;i<L.length;i++){
printf("%d\t",L.data[i]);
}
printf("\n");
printf("删除的数据为%d\n",e);
return 0;
}
运行结果:
5.线性表的按位查找
6.线性表的按值查找
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10 //定义线性表的最大长度
using namespace std;
typedef struct{
int data[MaxSize];//用静态的“数组”存放数据元素
int length;//顺序表的当前长度
}SqList;//顺序表的类型定义
void InitList(SqList &L){
for(int i=0;i<MaxSize;i++) //将数据初始化
L.data[i]=0;
L.length=0; //顺序表的初始长度为0
}
int LocateFind(SqList &L,int e){//按值查找回复位序
for(int i=0;i<L.length;i++){
if(L.data[i]==e){
return i+1;
}
}
return 0;//说明查找失败
}
int main(){
SqList L;
InitList(L);
for(int i=0;i<5;i++){
L.data[i]=i;
++L.length;
}
printf("length%d\n",L.length);
for(int i=0;i<L.length;i++){
printf("%d\t",L.data[i]);
}
printf("\n");
printf("查找到的数据位序%d\n",LocateFind(L,3));
return 0;
}
运行结果:
三、单链表的基本操作
1、用代码定义一个单链表
(1)定义单链表
typedef struct LNode{ //定义单链表节点类型
ElemType data; //每个节点存放一个数据元素,ElemType可为任意类型
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//使用LinkList强调这是个单链表,使用LNode *强调返回的是一个结点,二者意思一样,强调对象不同
LNode *GetElem(LinkList L,int i){
int j=1;
LNode *p=L->next;
if(i==0)
return L;
if(i<1)
return NULL;
while(p!=NULL&&j<i){
p=p->next;
j++;
}
return p;
}
(2)不带头结点的单链表
typedef struct LNode{ //定义单链表节点类型
ElemType data; //每个节点存放一个数据元素,ElemType可为任意类型
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//初始化一个空的单链表
bool InitList(LinkList &L){
L=NULL; //空表,暂时还没有任何结点,防止脏数据
return true;
}
void test(){
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
//初始化一个空表
InitList(L);
//后续代码.....
}
//判断单链表是否为空
bool Empty(LinkList L){
return (L==NULL);
}
(3)带头结点的单链表
typedef struct LNode{ //定义单链表节点类型
ElemType data; //每个节点存放一个数据元素,ElemType可为任意类型
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);
//后续代码.....
}
2.按位序插入
(1)带头结点按位序插入
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//初始化一个空的单链表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后暂时还没有结点
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
return 0;
}
运行结果:
(2)不带头结点按位序插入
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
if(i==1){//插入第一个结点的操作与其他结点操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true;
}
LNode *p; //指针p指向当前扫描到的结点
int j=1; //表示当前指针p指向的是第几个结点,不带头结点从1开始
p = L; //L指向头结点,头结点是第1个结点
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
L=NULL; //空表
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
return 0;
}
运行结果:
3.指定结点的插入操作
(1)指定结点的后插操作
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
if(i==1){//插入第一个结点的操作与其他结点操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true;
}
LNode *p; //指针p指向当前扫描到的结点
int j=1; //表示当前指针p指向的是第几个结点,不带头结点从1开始
p = L; //L指向头结点,头结点是第1个结点
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
L=NULL; //空表
return true;
}
//在P节点之后插入元素
bool InsertNextNode(LNode *p,int 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;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点后输入:");
scanf("%d",&n);
LNode *p=L;
int j=1;
while(p!=NULL&&j<n-1){
p=p->next;
j++;
}
if(p==NULL){
printf("你的输入不正确");
}
if(InsertNextNode(p,100)){
printf("指定节点后插成功\n");
}
else{
printf("指定节点后插失败\n");
}
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
return 0;
}
运行结果:
(2)带头结点的指定位置的后插操作
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//初始化一个空的单链表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后暂时还没有结点
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点后输入:");
scanf("%d",&n);
if(ListInsert(L,n+1,100)){
printf("指定节点后插成功\n");
}
else{
printf("指定节点后插失败\n");
}
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
return 0;
}
运行结果:
(3)不带头节点的指定位置后插操作
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
if(i==1){//插入第一个结点的操作与其他结点操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true;
}
LNode *p; //指针p指向当前扫描到的结点
int j=1; //表示当前指针p指向的是第几个结点,不带头结点从1开始
p = L; //L指向头结点,头结点是第1个结点
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
L=NULL; //空表
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点后输入:");
scanf("%d",&n);
if(ListInsert(L,n+1,100)){
printf("指定节点后插成功\n");
}
else{
printf("指定节点后插失败\n");
}
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
return 0;
}
运行结果:
(4)带头结点指定节点的前插操作
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//初始化一个空的单链表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后暂时还没有结点
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点前输入:");
scanf("%d",&n);
if(ListInsert(L,n,100)){
printf("指定节点前插成功\n");
}
else{
printf("指定节点前插失败\n");
}
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
return 0;
}
运行结果:
(5)不带头节点的前插操作
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
if(i==1){//插入第一个结点的操作与其他结点操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true;
}
LNode *p; //指针p指向当前扫描到的结点
int j=1; //表示当前指针p指向的是第几个结点,不带头结点从1开始
p = L; //L指向头结点,头结点是第1个结点
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
L=NULL; //空表
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点前输入:");
scanf("%d",&n);
if(ListInsert(L,n,100)){
printf("指定节点前插成功\n");
}
else{
printf("指定节点前插失败\n");
}
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
return 0;
}
运行结果:
(6)指定结点的前插操作(采用交换覆盖的方法)
//前插操作,在p结点之前插入结点
bool InsertPriorNode(LNode *p,LNode *s){
if(p==NULL || s==NULL){
return false;
}
s->next=p->next;
p->next=s;
int temp=p->data;
p->data=s->data;
s->data=temp;
return true;
}
4.按位序删除
(1)带头结点的按位序删除
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
if(i<1)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点,不带头结点从1开始
p = L; //L指向头结点,头结点是第1个结点
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
if(p->next==NULL)//第i-1个结点之后已无其它结点
return false;
LNode *q=p->next;//令q指向被删除的结点
e=q->data;//用e返回被删除的元素
p->next=q->next;//将*q结点从链中断开
free(q);
return true;//插入成功
}
//初始化一个空的单链表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后暂时还没有结点
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
int e=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入删除的结点位序:");
scanf("%d",&n);
if(ListDelete(L,n,e)){
printf("指定节点删除成功:%d\n",e);
}
else{
printf("指定节点删除失败\n");
}
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
return 0;
}
运行结果:
(2)不带头结点按位序删除
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,int e){
if(i<1)
return false;
if(i==1){//插入第一个结点的操作与其他结点操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true;
}
LNode *p; //指针p指向当前扫描到的结点
int j=1; //表示当前指针p指向的是第几个结点,不带头结点从1开始
p = L; //L指向头结点,头结点是第1个结点
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
if(i<1)
return false;
if(i==1){//删除第一个结点的操作与其他结点操作不同
e=L->data;
L=L->next;//头指针指向新结点
return true;
}
LNode *p; //指针p指向当前扫描到的结点
int j=1; //表示当前指针p指向的是第几个结点,不带头结点从1开始
p = L; //L指向头结点,头结点是第1个结点
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
if(p==NULL) //i值不合法,i大于链表长度
return false;
if(p->next==NULL)//第i-1个结点之后已无其它结点
return false;
LNode *q=p->next;//令q指向被删除的结点
e=q->data;//用e返回被删除的元素
p->next=q->next;//将*q结点从链中断开
free(q);
return true;//插入成功
}
//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
L=NULL; //空表
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
int e=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsert(L,1,3)&&ListInsert(L,2,4)&&ListInsert(L,3,5)){
printf("插入成功!\n");
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入删除的结点位序:");
scanf("%d",&n);
if(ListDelete(L,n,e)){
printf("指定节点删除成功:%d\n",e);
}
else{
printf("指定节点删除失败\n");
}
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
return 0;
}
运行结果:
(3)指定节点的删除
若p刚好是最后一个结点,会出现空指针错误
//删除结点p
bool DeleteNode(LNode *p){
if(p==NULL)
return false;
LNode *q=p->next;//令q指向被删除的结点
e=q->data;//用e返回被删除的元素
p->next=q->next;//将*q结点从链中断开
free(q);
return true;
}
5.封装综合
按位查找或者按值查找并进行封装删除,后插,前插,求表长操作
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//按位查找
LNode *GetElem(LinkList L,int i){
if(i<0)
return NULL;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
return p;
}
//按值查找
LNode *LocateElem(LinkList L,int e){
LNode *p=L->next;
//从第一个结点开始查找数据域为e的结点
while(p!=NULL&&p->data!=e)
p=p->next;
return p;//找到后返回该结点指针,否则返回NULL
}
//删除结点p
bool DeleteNode(LNode *p,int &e){
if(p==NULL)
return false;
LNode *q=p->next;//令q指向被删除的结点
e=q->data;//用e返回被删除的元素
p->next=q->next;//将*q结点从链中断开
free(q);
return true;
}
//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
if(i<1)
return false;
LNode *p=GetElem(L,i);//找到第i-1个结点
if(p==NULL) //i值不合法,i大于链表长度
return false;
if(p->next==NULL)//第i-1个结点之后已无其它结点
return false;
return DeleteNode(p,e);
}
//前插操作,在p结点之前插入结点
bool InsertPriorNode(LNode *p,int 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;
int temp=p->data;
p->data=s->data;
s->data=temp;
return true;
}
//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int 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;
}
//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p=GetElem(L,i);//找到第i个结点
return InsertNextNode(p,e);//插入成功
}
//在第i个位置前插入元素e
bool ListInsertPrior(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p=GetElem(L,i+1);//找到第i个结点
return InsertPriorNode(p,e);//插入成功
}
//求表的长度
int Length(LinkList L){
int len=0;
LNode *p=L;
while(p->next!=NULL){
p=p->next;
len++;
}
return len;
}
//输出函数
void print(LinkList L){
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}
//初始化一个空的单链表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后暂时还没有结点
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
int n=0;
int e=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
printf("插入成功!\n");
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点后输入:");
scanf("%d",&n);
if(ListInsertNext(L,n+1,100)){
printf("指定节点后插成功\n");
}
else{
printf("指定节点后插失败\n");
}
print(L);
n=0;
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点前输入:");
scanf("%d",&n);
if(ListInsertPrior(L,n,100)){
printf("指定节点前插成功\n");
}
else{
printf("指定节点前插失败\n");
}
print(L);
n=0;
printf("\n");
//在第n个节点后面插入元素e
printf("请输入删除的结点位序:");
scanf("%d",&n);
if(ListDelete(L,n,e)){
printf("指定节点删除成功:%d\n",e);
}
else{
printf("指定节点删除失败\n");
}
print(L);
printf("\n");
printf("表的长度:%d",Length(L));
return 0;
}
运行结果:
6.尾插法建立单链表
(1)带头结点尾插法
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//按位查找第i-1个结点
LNode *GetElem(LinkList L,int i){
if(i<0)
return NULL;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
return p;
}
//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int 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;
}
//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p=GetElem(L,i);//找到第i个结点
return InsertNextNode(p,e);//插入成功
}
//输出函数
void print(LinkList L){
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}
//初始化一个空的单链表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后暂时还没有结点
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
printf("插入成功!\n");
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
return 0;
}
运行结果:
(2)不带头节点的尾插法
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//按位查找第i-1个结点
LNode *GetElem(LinkList L,int i){
LNode *p; //指针p指向当前扫描到的结点
int j=1; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){//循环找到第i-个结点
p=p->next;
j++;
}
return p;
}
//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int 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;
}
//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
if(i<1)
return false;
if(i==1){//插入第一个结点的操作与其他结点操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true;
}
LNode *p=GetElem(L,i);//找到第i个结点
return InsertNextNode(p,e);//插入成功
}
//输出函数
void print(LinkList L){
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}
//不带头结点初始化一个空的单链表
bool InitList(LinkList &L){
L=NULL; //空表
return true;
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
printf("插入成功!\n");
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
return 0;
}
运行结果:
7.头插法建立单链表
(1)带头结点头插法
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode));//创建头结点
L->next=NULL;
printf("输入结点的值(9999视为退出):\n");
scanf("%d",&x);//输入结点的值
while(x!=9999){
s=(LNode *)malloc(sizeof(LNode));//创建新结点
s->data=x;
s->next=L->next;
L->next=s;//将新结点插入表中,L为头指针
scanf("%d",&x);
}
return L;
}
//求表的长度
int Length(LinkList L){
int len=0;
LNode *p=L;
while(p->next!=NULL){
p=p->next;
len++;
}
return len;
}
//输出函数
void print(LinkList L){
LNode *s=L->next;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
L=List_HeadInsert(L);
printf("单链表L:\n");
print(L);
printf("\n");
printf("表的长度:%d",Length(L));
return 0;
}
运行结果:
(2)不带头结点头插法
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
LNode *s;
int x;
L=NULL;//建立一个空的没有头结点的单链表
printf("输入结点的值(9999视为退出):\n");
scanf("%d",&x);//输入结点的值
while(x!=9999){
s=(LNode *)malloc(sizeof(LNode));//创建新结点
s->data=x;
s->next=L;
L=s;
scanf("%d",&x);
}
return L;
}
//求表的长度
int Length(LinkList L){
int len=1;//从第一个开始,因为他没有头结点
LNode *p=L;
while(p->next!=NULL){
len++;
p=p->next;
}
return len;
}
//输出函数
void print(LinkList L){
LNode *s=L;
while(s){
printf("%d\t",s->data);
s=s->next;
}
}
int main()
{
LinkList L; //此处为声明一个指向单链表的指针,但是并没有创建一个结点
L=List_HeadInsert(L);
printf("单链表L:\n");
print(L);
printf("\n");
printf("表的长度:%d",Length(L));
return 0;
}
运行结果:
8.循环单链表
封装综合
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
typedef struct LNode{ //定义单链表节点类型
int data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//初始化一个循环单链表
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));//建立一个头结点
if(L==NULL)
return false;
L->next=L;//头结点next指向头结点
return true;
}
//判断循环单链表是否为空
bool Empty(LinkList &L){
if(L->next==L){
return true;
}
else
return false;
}
//判断p结点是否是循环单链表的尾结点
bool isTail(LinkList L,LNode *p){
if(p->next==L){
return true;
}
else
return false;
}
//按位查找i-1位
LNode *GetElem(LinkList L,int i){
if(i<0)
return NULL;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p->next!=L&&j<i-1){//循环找到第i-1个结点
p=p->next;
j++;
}
return p;
}
//按值查找
LNode *LocateElem(LinkList L,int e){
LNode *p=L->next;
//从第一个结点开始查找数据域为e的结点
while(p->next!=L&&p->data!=e)
p=p->next;
return p;//找到后返回该结点指针,否则返回NULL
}
//删除结点p的后继结点
bool DeleteNode(LNode *p,int &e){
if(p==NULL)
return false;
LNode *q=p->next;//令q指向被删除的结点
e=q->data;//用e返回被删除的元素
p->next=q->next;//将*q结点从链中断开
free(q);
return true;
}
//在第i个位置删除元素e
bool ListDelete(LinkList &L,int i,int &e){
if(i<1)
return false;
LNode *p=GetElem(L,i);//找到第i-1个结点
if(p==NULL) //i值不合法,i大于链表长度
return false;
if(p->next==NULL)//第i-1个结点之后已无其它结点
return false;
return DeleteNode(p,e);
}
//前插操作,在p结点之前插入结点
bool InsertPriorNode(LNode *p,int 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;
int temp=p->data;
p->data=s->data;
s->data=temp;
return true;
}
//后插操作,在P节点之后插入元素
bool InsertNextNode(LNode *p,int 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;
}
//在第i个位置插入元素e
bool ListInsertNext(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p=GetElem(L,i);//找到第i-1个结点
return InsertNextNode(p,e);//插入成功
}
//在第i个位置前插入元素e
bool ListInsertPrior(LinkList &L,int i,int e){
if(i<1)
return false;
LNode *p=GetElem(L,i+1);//找到第i个结点
return InsertPriorNode(p,e);//插入成功
}
//求表的长度
int Length(LinkList L){
int len=0;
LNode *p=L;
while(p->next!=L){
p=p->next;
len++;
}
return len;
}
//输出函数
void print(LinkList L){
LNode *s=L->next;
while(s->next!=L->next){
printf("%d\t",s->data);
s=s->next;
}
}
int main()
{
LinkList L; //此处为声明一个指向循环单链表的指针,但是并没有创建一个结点
int n=0;
int e=0;
//初始化一个空表
if(InitList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
printf("插入成功!\n");
LNode *s=L->next;
while(s->next!=L->next){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点后输入:");
scanf("%d",&n);
if(ListInsertNext(L,n+1,100)){
printf("指定节点后插成功\n");
}
else{
printf("指定节点后插失败\n");
}
print(L);
n=0;
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点前输入:");
scanf("%d",&n);
if(ListInsertPrior(L,n,100)){
printf("指定节点前插成功\n");
}
else{
printf("指定节点前插失败\n");
}
print(L);
n=0;
printf("\n");
//在第n个节点后面插入元素e
printf("请输入删除的结点位序:");
scanf("%d",&n);
if(ListDelete(L,n,e)){
printf("指定节点删除成功:%d\n",e);
}
else{
printf("指定节点删除失败\n");
}
print(L);
printf("\n");
printf("表的长度:%d",Length(L));
return 0;
}
运行结果:
四、双链表的基本操作
1.双链表与循环双链表的区别
双链表:
表头结点的prior指向NULL;
表尾结点的next指向NULL。
循环双链表:
表头结点的prior指向表尾结点;
表尾结点的next指向头结点。
2.循环双链表的基本操作
封装综合
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
//定义一个双链表
typedef struct DNode{
int data;
struct DNode *prior,*next;
}DNode,*DLinkList;
//初始化空的循环双链表
bool InitDLinkList(DLinkList &L){
L = (DNode *)malloc(sizeof(DNode));//分配一个头结点
if(L==NULL)
return false;
//头结点的prior和next都指向头结点
L->prior=L;
L->next=L;
return true;
}
//判断循环双链表是否为空
bool Empty(DLinkList L){
if(L->next==L)
return true;
else
return false;
}
//判断结点p是否为循环双链表的表尾结点
bool isTail(DLinkList L,DNode *p){
if(p->next==L)
return true;
else
return false;
}
//按位查找i-1位
DNode *GetElem(DLinkList L,int i){
if(i<0)
return NULL;
DNode *p; //指针p指向当前扫描到的结点
int j=0; //表示当前指针p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p->next!=L&&j<i-1){//循环找到第i-1个结点
p=p->next;
j++;
}
return p;
}
//删除结点p的后继结点
bool DeleteDNode(DNode *p,DNode *q,int &e){
if(p==NULL)
return false;
p->next=q->next;
e=q->data;//用e返回被删除的元素
q->next->prior=p;//将*q结点从链中断开
free(q);
return true;
}
//在第i个位置删除元素e
bool ListDelete(DLinkList &L,int i,int &e){
if(i<1)
return false;
DNode *p=GetElem(L,i);//找到第i-1个结点
DNode *q=p->next;
if(p==NULL) //i值不合法,i大于链表长度
return false;
return DeleteDNode(p,q,e);
}
//后插操作,在P节点之后插入元素
bool InsertNextNode(DNode *p,int e){
if(p==NULL)
return false;
DNode *s=(DNode *)malloc(sizeof(DNode));
//内存分配失败
if(s==NULL)
return false;
s->data=e;
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
//在第i个位置插入元素e
bool ListInsertNext(DLinkList &L,int i,int e){
if(i<1)
return false;
DNode *p=GetElem(L,i);//找到第i-1个结点
return InsertNextNode(p,e);//插入成功
}
//求表的长度
int Length(DLinkList L){
int len=0;
DNode *p=L;
while(p->next!=L){
p=p->next;
len++;
}
return len;
}
//输出函数
void print(DLinkList L){
DNode *s=L->next;
while(s->next!=L->next){
printf("%d\t",s->data);
s=s->next;
}
}
int main()
{
//初始化一个循环双链表
DLinkList L;
int n=0;
int e=0;
//初始化一个空表
if(InitDLinkList(L))
printf("初始化成功");
printf("\n");
//后续代码.....
if(ListInsertNext(L,1,3)&&ListInsertNext(L,2,4)&&ListInsertNext(L,3,5)){
printf("插入成功!\n");
DNode *s=L->next;
while(s->next!=L->next){
printf("%d\t",s->data);
s=s->next;
}
}else{
printf("插入失败\n");
}
printf("\n");
//在第n个节点后面插入元素e
printf("请输入在第几个节点后输入:");
scanf("%d",&n);
if(ListInsertNext(L,n+1,100)){
printf("指定节点后插成功\n");
}
else{
printf("指定节点后插失败\n");
}
print(L);
n=0;
printf("\n");
//在第n个节点后面插入元素e
printf("请输入删除的结点位序:");
scanf("%d",&n);
if(ListDelete(L,n,e)){
printf("指定节点删除成功:%d\n",e);
}
else{
printf("指定节点删除失败\n");
}
print(L);
printf("\n");
printf("表的长度:%d",Length(L));
return 0;
}
运行结果:
五、静态链表
#define MaxSize 10 //静态链表的最大长度
typedef struct{ //静态链表结构类型的定义
ElemType data; //存储数据元素
int next; //下一个元素的数组下标
}SLinkList[MaxSize]