数据结构(C语言描述)(王爱民 李杰)清华大学出版学习课后题第三章(顺序表,链表,串的KMP算法)

本文详细介绍了顺序表和链表的基本概念及其实现方式,包括初始化、插入、删除等操作,并提供了完整的C语言代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

顺序表

了解顺序表的前提就是知道什么是线性表,线性表的概念非常的简单,就是除了头和尾元素之外的所有元素都有一个前驱和一个后继,满足这样要求的我们基本上都可以定义为线性表。

那么线性表我们在这里会讲述其中的两种

顺序线性表----逻辑和物理位置都是相邻的线性表叫做顺序表。

那么废话我们就谈到这,给出一个顺序表的代码,但是还是未完成版,我在网上看到他们给出了一个顺序表的完整版(18个函数)我就完成了其中的几个。。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define maxsize 10
typedef struct 
{
	int data[maxsize];
	int last;
}sqlist;//顺序表定义

sqlist *inti_sqlist()
{
	sqlist *l;
	l = (sqlist *)malloc(sizeof(sqlist));
	l->last = -1;
	return l;


}// 初始化
int find_element_location(sqlist *l,int elem)
{
	int i=0;
	while(i<l->last&&l->data[i]!=elem)
		i++;
	if (i>l->last)
		return -1;
	else
		return i;
}//查找数据元素的位置
int insert_element(sqlist *l,int i,int elem)
{
	if (l->last==maxsize-1)
	{
		printf("the list is full!\n");
		return -1;
	}
	if (i<1||i>l->last+2)
	{
		printf("wrong location!\n");
		return 0;
	}
	for (int j=l->last;j>=i-1;j--)
		l->data[j+1] = l->data[j];
	l->data[i-1]=elem;
	l->last++;
	return 1;
}
int delete_element(sqlist *l,int i)
{
	if (i<1||i>l->last+1)
	{
		printf("wrong location\n");
		return -1;
	}
	for (int j=i;j<l->last;j++)
		l->data[j]=l->data[j+1];
	l->last--;
	return 1;
}
void show(sqlist *l,int n)
{
	printf("the element of the sqlist is:\n");
	for (int i=0;i<n;i++)
	{
		printf("%d\t",l->data[i]);
	}
	printf("\n");
}
void createlist(sqlist *l,int n)
{
	for (int i=0;i<n;i++)
	{
		printf("please input the elem of list:");
		scanf("%d",&l->data[i]);
		l->last++;
	}
}
	
int main()
{
	sqlist *l;
	int number;
	int elem,position;
	l = inti_sqlist();
	printf("please input how many number do you want to:\n");
	scanf("%d",&number);
	createlist(l,number);
	show(l,number);
	while(1)
	{
		printf("please input the elem:");
		scanf("%d",&elem);
		fflush(stdin);
		if (elem==000)
		{
			printf("the choose is quit!\n ");
			break;
		}
		printf("please input where do you want to insert:");
		scanf("%d",&position);
		fflush(stdin);
		insert_element(l,position,elem);//增加一个元素
		//printf("%d\n",l->last);
		number++;
		show(l,number);
	}
	while(1)
	{
		int position;
		printf("please input which one do you want to delete:");
		scanf("%d",&position);
		fflush(stdin);
		delete_element(l,position);
		number--;
		show(l,number);
	}
	system("pause");
	return 0;
}

代码不难,很简单,不分析!!大笑

链表

我们一般对链表可以讲有以下一些情况,单链表,循环链表,双向链表

单链表顾名思义,就是从头开始,不能回溯,一切都是从头开始。

循环链表就是在在单链表的基础上,使得最后一个元素的指针不是指向空而是指向第一个元素。

双线链表单链表的基础上加了一个指向前驱的一个指针。

代码之伺候:

#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
typedef int elemtype;
typedef struct node
{
	elemtype elem;
	struct node *next;
}LNode,*linkList;
//初始化一个空链表
linkList InitLinkList()
{
	LNode *L;
	L=(LNode *)malloc(sizeof(LNode));
	if (L==NULL)
		printf("申请空间失败!\n");//如果申请空间失败的话,表明不正确 
	L->next=NULL;//空表头指针指向空
	return 0;
	
}
//从头插入建立一个单链表
linkList create_linklist_by_head()
{
	LNode *L;
	L = (LNode *)malloc(sizeof(LNode));
	if (L==NULL)
		printf("申请空间失败!\n");//如果申请空间失败的话,表明不正确 
	L->next=NULL;//空表头指针指向空
	elemtype x;
	LNode *s;
	printf("please input a element:");
	while(scanf("%d",&x)!=EOF)
	{
		s=(LNode *)malloc(sizeof(LNode));
		s->elem = x;
		s->next = L->next;
		L->next = s;
		printf("please input a element:");
	}
	return L;
}
//从尾插入建立一个单链表
linkList create_linklist_by_rear()
{
	LNode *L;
	L = (LNode *)malloc(sizeof(LNode));
	if (L==NULL)
		printf("申请空间失败!\n");//如果申请空间失败的话,表明不正确 
	L->next=NULL;//空表头指针指向空
	LNode *rear;//设定一个尾指针
	rear = L;
	elemtype x;
	LNode *s;
	printf("please input a element:");
	while(scanf("%d",&x)!=EOF)
	{
		s=(LNode *)malloc(sizeof(LNode));
		s->elem = x;
		rear->next = s;
		rear=s;
		printf("please input a element:");
	}
	rear->next = NULL;
	return L;
}
//求单链表的长度
int length_of_linklist(linkList L)
{
	int length=0;
	LNode *head;
	head = L;
	while(head->next!=NULL)
		{
			head = head->next;
			length++;
		}
	return length;
}
//按序号查询单链表
LNode *search_by_ID(linkList L,int i)
{
	LNode *head = L;
	int j=0;
	while(head->next!=NULL&&j<i)
	{
		head = head->next;
		j++;
	}
	if (j==i)
		return head;
	else
		return NULL;
}
//按值查询单链表
int search_by_value(linkList L,elemtype x)
{
	LNode *head = L;
	int j=0;
	while(head->next!=NULL && head->elem!=x)
		{
			head = head->next;
			j++;
		}
	if (head->elem==x)
			return j;	
	else
		return -1;
}
//单链表的前插
linkList list_insert_before(LNode *L,int i,elemtype elem)
{
	LNode *head,*s;
	head = L;
	s = (LNode *)malloc(sizeof(LNode));
	s->elem = elem;
	s->next = search_by_ID(L,i-1)->next;//做了个小把戏,前插就是前一个元素的后插(没含金量)
	search_by_ID(L,i-1)->next = s;
	return L;
}
//单链表的后插
linkList list_insert_after(LNode *L,int i,elemtype elem)
{
	LNode *head = L;
	LNode *s;
	s = (LNode *)malloc(sizeof(LNode));
	s->elem = elem;
	s->next = search_by_ID(L,i)->next;
	search_by_ID(L,i)->next = s;
	return L;
}

linkList delete_elem(linkList L,elemtype x)
{
	LNode *head;
	head = L->next;
	LNode *s;
	while(head->elem!=x)
	{
		s = head;
		head = head->next;
	}
	s->next = head->next;
	free(head);
	return L;
}
void show(linkList list)
{
	linkList start;
	//list = InitLinkList();
	for(start = list->next;start!=NULL;start=start->next)
		printf("%d\t",start->elem);
}
int main()
{
	linkList list;
	int position;
	elemtype elem;
	list = InitLinkList();
	printf("请输入单链表的数据:\n");
	//list = create_linklist_by_head();
	list = create_linklist_by_rear();
	show(list);
	printf("单链表长度是:%d\n",length_of_linklist(list));
	/////////////////////////////////////////////////////////////////////验证search_by_ID
	printf("输入你想查询的位置:");
	scanf("%d",&position);
	
	if(search_by_ID(list,position))
		printf("你查询的位置的元素是:%d\n",search_by_ID(list,position)->elem);
	else
		printf("没有这个元素");
	///////////////////////////////////////////////////////////////////验证search_by_value
	printf("输入你想查询的元素:");
	scanf("%d",&elem);
	if(search_by_value(list,elem)!=-1)
		printf("你查询的元素位置是:%d\n",search_by_value(list,elem));
	else
		printf("没有这个元素");
	///////////////////////////////////////////////////////////后插法
	printf("输入你想插入的位置:");
	scanf("%d",&position);
	printf("输入你想插入的元素:");
	scanf("%d",&elem);
	fflush(stdin);
	list_insert_after(list,position,elem);
	show(list);
	printf("\n");
	////////////////////////////////////////////////////////前插法
	printf("输入你想插入的位置:");
	scanf("%d",&position);
	printf("输入你想插入的元素:");
	scanf("%d",&elem);
	fflush(stdin);
	list_insert_before(list,position,elem);
	show(list);
	printf("\n");
	/////////////////////////////////////////删除元素
	printf("输入你想删除的位置:");
	scanf("%d",&position);
	delete_elem(list,position);
	show(list);
	printf("\n");
	system("pause");
	return 0;
}

分的情况比较多,其实核心的东西非常的少,非常的少,就是加入了一些情况,什么前插后插啊,头插尾插啊之类的,代码就显得冗余了!!!

其实这个概念可以不说的,因为C++中有个类叫string,这个类基本上把C语言中的串中的所有功能全实现了,而且还添加了很多的功能,所以,我感觉太多的研究这个意义不是特别的大。

这里讲一下KMP算法,就我个人而言,我到现在为止还没有搞明白这个算法,尤其是其中的next函数的求法,网上给的方法五花八门,我没有搞定,有大神有好的方法或者是帖子希望不吝赐教!!

也把代码放在这,但是有bug

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

int strIndex_KMP(char *s,char *t,int position)//KMP算法
{
	int i=position,j=1,slen,tlen;
	while(i<=s[0]&&j<=t[0])
			if (j==0||s[i]==t[j])
			{
				i++;
				j++;
			}
			if (j>t[0])
				return i-t[0];
			else
				return -1;
}
void getNext(char *ss,int next[])//next函数
{
	next[1] = 0;
	int j=1,k=0;
	while(j<ss[0])
	{
		if ((k==0)||(ss[j]==ss[k]))
		{
			j++;
			k++;
			next[j] = k;
		}
		else
			k = next[k];
	}
	/*next[0]=-1;
	int k=-1,j=0;
	while(pattern[j]!='\0')
	{
		while(k!=-1&&pattern[k]!=pattern[j])k=next[k];
		++j;
		++k;
		if(pattern[k]==pattern[j])
			next[j]=next[k];
		else next[j]=k;
	}*/
}
int main()
{
	char *s = "aabcbabcaabcaababc";
	char *t = " abaabcac";
	int tlength = strlen(t);
	printf("the length of string t is %d\n",tlength);
	int *next = (int *)malloc(tlength*sizeof(int));
	//int next[9]={0};
	for (int i=0;i<tlength;i++)
	{
		next[i] = 0;
	}
	//int next[9];
	getNext(t,next);
	printf("the array of next is:\n");
	for(int i=0;i<tlength;i++)
		printf("%d\t",next[i]);
	printf("the position of finding is:%d\n",strIndex_KMP(s,t,0));
	system("pause");
	return 0;
}

大哭搞不定!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值