求线性表在链接存储结构下插入与删除的完整源代码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求线性表在链接存储结构下插入与删除的完整源代码相关的知识,希望对你有一定的参考价值。

要链接存储结构的,而且数据是用产生随机数的方法来得到随机整数
这里有算法参考
int Insert_LinkList(LinkList L,int i,datatype x)

LNode *p,*s;
p=Get_LinkList(L,i-1);
if(p==NULL)

printf("参数i错");
return 0;

else

s=(LNode *)malloc(sizeof(LNode));
s->data=x;
s->next=p->next;
p->next=s;
return 1;



int Del_LinkList(LinkList L,int i)

LinkList p,s;
p=Get_LinkList(L,i-1);
if(p==NULL)

printf("第i-1个结点不存在");
return -1;

else
if(p->next==NULL)

printf("第i个结点不存在");
return 0;

else

s=p->next;
p->next=s->next;
free(s);
return 1



哪位大侠帮帮忙,呵呵

参考技术A #include"stdio.h"
#include<malloc.h>
#include<stdlib.h>
#include"time.h"

typedef char ElemType;

typedef struct LNode
ElemType data;
struct LNode *next;
LinkList;

void CreateListR(LinkList *&L,ElemType a[],int n) //尾插法建表

LinkList *s,*r;int i;
L=(LinkList *)malloc(sizeof(LinkList));
r=L;
for(i=0;i<n;i++)

s=(LinkList *)malloc(sizeof(LinkList));
s->data=a[i];
r->next=s;
r=s;

r->next=NULL;


void InitList(LinkList *&L) //初始化线性表

L=(LinkList *)malloc(sizeof(LinkList));
L->next=NULL;


void DispList(LinkList *L) //输出线性表

LinkList *p=L->next;
while(p!=NULL)

printf("%c",p->data);
p=p->next;



void CombList(LinkList *L1,LinkList *L2,LinkList *&k) //两个集合的交

LinkList *p=L1->next ,*q=L2->next ,*b,*a,*c;

k=(LinkList *)malloc(sizeof(LinkList));
b=k;a=p;
while(q!=NULL)

while(a!=NULL)

if(a->data==q->data)

c=(LinkList *)malloc(sizeof(LinkList));
c->data=a->data;b->next=c;b=b->next;

a=a->next;

q=q->next;
a=p;

b->next=NULL;


void AddList(LinkList *L1,LinkList *L2,LinkList *&k) //两个集合的并

LinkList *p=L1->next ,*q=L2->next ,*b,*a,*c;

k=(LinkList *)malloc(sizeof(LinkList));
b=k;a=p;

while(q!=NULL)

int x=0;
while(p!=NULL)

if(p->data==q->data)x++;
p=p->next;

if(!x)

c=(LinkList *)malloc(sizeof(LinkList));
c->data=q->data;b->next=c;b=b->next;

q=q->next;
p=a;

b->next=a;


void RankList(LinkList *&L) //按从小到大排列

LinkList *p=L->next,*q,*r;
if (p!=NULL)
r=p->next;
p->next=NULL;
p=r;
while (p!=NULL)
r=p->next;
q=L;
while (q->next!=NULL && q->next->data<p->data)
q=q->next;
p->next=q->next;
q->next=p;
p=r;



int main()

ElemType a[5];
LinkList *h1;

srand(time(0));
for(int i=0;i<5;i++)
a[i]=rand()%27+'a';
InitList(h1); //初始化顺序表h
CreateListR(h1,&a[0],5); //依次采用尾插入法插入a,b,c,d,e元素

printf("单链表为:");
DispList(h1); printf("\n"); //输出顺序表h

return 0;


你看看符合要求不。
参考技术B //main函数我是为了测试才这样写的;至于其他你可以自己在main函数里面改
//如果觉得够完整的话就给分吧^_^ 偶写的很辛苦哦。。。。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define LEN sizeof(node)
typedef int datatype;
typedef struct node

datatype num;
struct node* next;
node,*link;
link Create_list(void); //创建链表
link Get_LinkList(link head,int i); //取得第i个节点的地址
int Insert_List(link head,int i,datatype x); //插入
int Del_list(link head,int i); //删除第i个节点
void Display(link head); //显示
int main ()

link head=NULL,p=NULL;
int i,x,(*q)()=Insert_List; //int (*q)()=Insert_List;是一个指向函数的指针
head=Create_list();
printf("输入节点位置");
scanf("%d",&i);
p=Get_LinkList(head,i);
if(p)
printf("这个节点的值:%d\n",p->num);
else
printf("这个节点不存在\n");
printf("输入插入位置和插入值:\n");
scanf("%d%d",&i,&x);
if((*q)(head,i,x))

printf("插入成功!\n插入后为:\n");
Display(head);

else
printf("插入不成功!\n");
printf("输入删除位置:");
scanf("%d",&i);
if(Del_list(head,i))

printf("删除成功!\n删除后为:\n");
Display(head);

else
printf("删除失败!\n");
return 0;

link Create_list()

link head,p,last;
int x,n;
printf("请输入输入个数:");
scanf("%d",&n);
last=head=(link)malloc(LEN); //建立头结点 last指向最后一个节点
srand(time(NULL)); //为产生随机数设置种子
while(n--)

x=rand()%201; //产生0~200之间的随机数
p=(link)malloc(LEN);
p->num=x;
last->next=p; //将新的节点p节点最后一个节点之后
last=p; //更新last的指向,让它永远都指向当前链表的尾节点

last->next=NULL; //将最后一个节点的指针域置空
return head;

/*功能:得到第i个节点的地址*/
link Get_LinkList(link head,int i)

link p=head;
int n=0;
while(p->next!=NULL&&n<i) //如果还没有到表尾且p指向的还不是第i个节点

p=p->next;
n++;

if(n==i) //如果找到第i个节点
return p; //将其地址返回
else
return NULL; //否则返回null

/*功能:将值x插入到链表的第i个位置之前*/
int Insert_List(link head,int i,datatype x)

link p,q;
p=Get_LinkList(head,i-1);
if(p)

q=(link)malloc(LEN);
q->num=x;
q->next=p->next;
p->next=q;
return 1;

else
return 0;

int Del_list(link head,int i)

link p,pr;
p=Get_LinkList(head,i); //查找第i个节点
if(p) //如果p!=NULL则表明p第i个节点是存在的

pr=Get_LinkList(head,i-1);
pr->next=p->next;
free(p);
return 1;

else //否则返回0表示删除不成功
return 0;

void Display(link head)

link p=head->next;
while(p)

printf("%d\t",p->num);
p=p->next;

本回答被提问者采纳

数据结构之单链表

简介

线性表的顺序存储结构有一个缺点就是插入和删除时需要移动大量元素,这会耗费许多时间。能不能想办法解决呢?
干脆所有的元素都不要考虑相邻位置了,哪有空位就到哪里,让每一个元素都知道它下一个元素的位置在哪里。
线性表链式存储结构: 用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。
链表是由一个个结点链结成的。
结点包括数据域和指针域两部分,数据域用来存储数据元素的信息,指针域用来存储下一个结点的地址。
接下来实现一个无头单向非循环链表。

单链表结构的定义

typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;		//数据
	struct SListNode* next;		//指向下一个结点的指针
}SLTNode;

单链表打印

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur)
	{
		printf("%d -> ", cur->data);
		cur = cur->next;
	}
	printf("NULL\\n");
}


将指向链表的指针plist做参数传给函数,遍历一遍链表并输出每个结点数据域的内容。

动态申请一个结点

SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));
	if (node == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	node->data = x;
	node->next = NULL;
	return node;
}

用malloc动态开辟一个结点,如果node为NULL说明开辟失败,退出程序。否则将结点node的数据域赋值为x,指针域赋值为NULL。

单链表尾插

如果单链表为空,开辟一个新结点用指针指向它即可;如果链表不为空,需要开辟一个新结点,然后找到链表的最后一个结点,让最后一个结点的指针域存放新结点的地址。
有一个链表,为链表尾插一个新结点:


void SListPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);		//plist地址一定不为NULL,进行断言
	if (*pphead == NULL)	//链表为空
	{
		SLTNode* newnode = BuySListNode(x);
		*pphead = newnode;
	}
	else           //链表不为空
	{		
		SLTNode* tail = *pphead;
		while (tail->next)		//找到最后一个结点
			tail = tail->next;
		SLTNode* newnode = BuySListNode(x);
		tail->next = newnode;
	}
}


为指针不好的同学解释下参数,plist为指向结构体的指针,指向链表的头结点,打印函数的形参phead为plist的一个临时拷贝,作用和plist是一样的,这里的尾插函数pphead为指针plist的地址,是一个二级指针。因为当链表为空时,会改变指针的指向,所以参数用二级指针。

单链表尾删

如果链表只有一个结点,把这个结点free掉即可。如果链表有多个结点,找到链表的尾结点和尾结点的前一个结点,让尾结点的前一个结点的指针域指向NULL,free掉尾结点。

void SListPopBack(SLTNode** pphead)
{
	assert(pphead);		//断言pphead
	assert(*pphead);	//当链表为空时说明没有结点,没法进行删除操作,所以*pphead不能为NULL
	if ((*pphead)->next == NULL)	//只有一个结点
	{
		free(*pphead);
		*pphead = NULL;
	}
	else                //多个结点
	{
		SLTNode* tail = *pphead;	//tail表示为节点
		SLTNode* prev = NULL;		//prev表示尾结点的前一个结点
		while (tail->next)		//找到尾结点和尾结点的前一个结点
		{
			prev = tail;
			tail = tail->next;
		}
		prev->next = NULL;
		free(tail);
		tail = NULL;
	}
}

单链表头插

申请一个新结点,让新结点的指针域存放头结点的地址,原来指向头结点的指针plist指向新结点,新结点就变成了新的头结点。

void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

单链表头删

用一个指针指向头结点的下一个结点,把头结点的空间释放掉,指向头结点的指针指向头结点的下一个结点。头结点的下一个结点就变成了新的头结点。同时要考虑链表为空时不能删除,进行相应的断言。

void SListPopFront(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	SLTNode* next = (*pphead)->next;	//指针next记录头结点的下一个结点
	free(*pphead);
	*pphead = next;
}

求单链表长度

int SListSize(SLTNode* phead)
{
	int size = 0;
	SLTNode* cur = phead;
	while (cur)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

单链表查找

遍历一遍单链表,如果某一结点数据域内容与要查找内容相同,返回该结点。遍历完没有找到,返回NULL。

SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (x == cur->data)
			return cur;
		cur = cur->next;
	}
	return NULL;
}

单链表在pos位置插入

在pos位置插入,如果pos这个位置是头结点,和头插的逻辑是一样的,可以调用之前写过的头插函数。
如果这个位置是除头结点外的任意一个结点,我们需要申请一个新结点,并且记录pos结点的前一个结点,让新结点的指针域存放pos的地址,让pos前一个结点的指针域存放新结点的地址,把它们链结起来。

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);		//指向头结点指针的地址不能为NULL,进行断言
	assert(pos);		//插入位置pos不能为NULL进行断言
	if (pos == *pphead)		//要插入的位置pos和头结点是一个位置
	{
		SListPushFront(pphead, x);
	}
	else                //pos不是头结点
	{
		SLTNode* prev = *pphead;    //prev用来找到pos位置的前一个结点
		while (prev->next != pos)
			prev = prev->next;
		SLTNode* newnode = BuySListNode(x);		//申请一个新结点
		newnode->next = pos;		//把新结点链结
		prev->next = newnode;
	}
}

单链表在pos后面位置插入

申请一个新结点,让新结点的指针域存放pos结点下一个结点的地址,pos结点的指针域存放新结点的地址。

void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

单链表删除pos位置

如果pos位置是头结点,删除逻辑和头删相同,调用头删函数即可。
如果是除头结点外的其它结点,找到pos的前一个结点,让这个结点的指针域指向pos的下一个结点。把pos结点空间释放。

void SListErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead);	//pphead不能为空,链表不能为空进行断言
	assert(pos);			//pos不能为空
	if (pos == *pphead)		//要删除的位置pos是头结点
	{
		SListPopFront(pphead);
	}
	else                    //不是头结点
	{
		SLTNode* prev = *pphead;	//prev指针用来找到pos结点的前一个结点
		while (prev->next != pos)
			prev = prev->next;
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

单链表删除pos的下一个结点

记录下pos的下一个结点,pos结点指针域指向pos下一个结点指针域指向的结点,释放掉pos的下一个结点。

void SListEraseAfter(SLTNode* pos)
{
	//pos不能为空,不能为尾结点,因为尾结点的下一个是NULL,什么也删除不了
	assert(pos && pos->next);	
	SLTNode* next = pos->next;		//next指针指向pos下一个结点
	pos->next = next->next;
	free(next);
	next = NULL;
}

判断单链表是否为空

bool SListEmpty(SLTNode* phead)
{
	return phead == NULL;
}

头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;		//数据
	struct SListNode* next;		//指向下一个结点的指针
}SLTNode;

//打印
void SListPrint(SLTNode* phead);
//新节点
SLTNode* BuySListNode(SLTDataType x);
//尾插
void SListPushBack(SLTNode** pphead, SLTDataType x);
//尾删
void SListPopBack(SLTNode** pphead);
//头插
void SListPushFront(SLTNode** pphead, SLTDataType x);
//头删
void SListPopFront(SLTNode** pphead);
//长度
int SListSize(SLTNode* phead);
//查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x);
//在pos位置插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//pos位置后面插入
void SListInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos位置
void SListErase(SLTNode** pphead, SLTNode* pos);
//删除pos后面位置
void SListEraseAfter(SLTNode* pos);
//判空
bool SListEmpty(SLTNode* phead);

源文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur)
	{
		printf("%d -> ", cur->data);
		cur = cur->next;
	}
	printf("NULL\\n");
}

SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));
	if (node == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	node->data = x;
	node->next = NULL;
	return node;
}

void SListPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);		//plist地址一定不为NULL,进行断言
	if (*pphead == NULL)	//链表为空
	{
		SLTNode* newnode = BuySListNode(x);
		*pphead = newnode;
	}
	else           //链表不为空
	{		
		SLTNode* tail = *pphead;
		while (tail->next)
			tail = tail->next;
		SLTNode* newnode = BuySListNode(x);
		tail->next = newnode;
	}
}

void SListPopBack(SLTNode** pphead)
{
	assert(pphead);		//断言pphead
	assert(*pphead);	//当链表为空时说明没有结点,没法进行删除操作,所以*pphead不能为NULL
	if ((*pphead)->next == NULL)	//只有一个结点
	{
		free(*pphead);
		*pphead = NULL;
	}
	else                //多个结点
	{
		SLTNode* tail = *pphead;	//tail表示为节点
		SLTNode* prev = NULL;		//prev表示尾结点的前一个结点
		while (tail->next)		//找到尾结点和尾结点的前一个结点
		{
			prev = tail;
			tail = tail->next;
		}
		prev->next = NULL;
		free(tail);
		tail = NULL;
	}
}

void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

void SListPopFront(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

int SListSize(SLTNode* phead)
{
	int size = 0;
	SLTNode* cur = phead;
	while (cur)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (x == cur->data)
			return cur;
		cur = cur->next;
	}
	return NULL;
}

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);		//指向头结点指针的地址不能为NULL,进行断言
	assert(pos);		//插入位置pos不能为NULL进行断言
	if (pos == *pphead)		//要插入的位置pos和头结点是一个位置
	{
		SListPushFront(pphead, x);
	}
	else                //pos不是头结点
	{
		SLTNode* prev = *pphead;    //prev用来找到pos位置的前一个结点
		while (prev->next != pos)
			prev = prev->next;
		SLTNode* newnode = BuySListNode(x);		//申请一个新结点
		newnode->next = pos;		//把新结点链结
		prev->next = newnode;
	}
}

void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

void SListErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead);	//pphead不能为空,链表不能为空进行断言
	assert(pos);			//pos不能为空
	if (pos == *pphead)		//要删除的位置pos是头结点
	{
		SListPopFront(pphead);
	}
	else                    //不是头结点
	{
		SLTNode* prev = *pphead;	//prev指针用来找到pos结点的前一个结点
		while (prev->next != pos)
			prev = prev->next;
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

void SListEraseAfter(SLTNode* pos)
{
	//pos不能为空,不能为尾结点,因为尾结点的下一个是NULL,什么也删除不了
	assert(pos && pos->next);	
	SLTNode* next = pos->next;		//next指针指向pos下一个结点
	pos->next = next->next;
	free(next);
	next = NULL;
}

bool SListEmpty(SLTNode* phead)
{
	return phead == NULL;
}

以上是关于求线性表在链接存储结构下插入与删除的完整源代码的主要内容,如果未能解决你的问题,请参考以下文章

用C语言建立一个顺序存储的线性表并实现线性表的插入和删除操作

数据结构之单链表

数据结构之单链表

数据结构之单链表

课本总结:1:线性表

课本总结:1:线性表