数据结构(单链表)-002

嗯,上一篇写的太过于臃肿了,在后续的文章中我就不将所有代码注释和函数一次性都写出来。避免大家阅读困难! 

单链表的定义:

单链表的链式存储结构和前面所讲的的线性表的顺序存储结构相比较它最大的特点就是单链表的的每一个元素

在内存中是不连续的,这导致了假如我们想要访问表中第i个位置的元素,就必须得到第i-1个元素的地址。我们访问单链表

中的元素都是通过头指针中指针域保存的地址来访问表中的元素,并且不能越级访问。因为每一个结点有且仅有一个保存下一个

结点的地址的指针域,我觉得这是它不方便的一个地方,因为每一次我们想要查找或者删除表中的元素时,我们必须从头指针开始遍历!尽管如此,但是单链表的插入和删除效率比之线性表还是高了去多(单链表在确定插入或删除结点的上一个结点的信息后,插入和删除时间仅为O(1),而线性表位O(n),这是因为线性表的插入和删除需要移动结点后面的所有元素);

单链表的结构体定义的成员有两个,一个是用来存储数据的数据域,另外一个是用来保存指向下一个结点地址的指针域。

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;
//初始化一个空的单链表


int main(void){
	LinkList* L=NULL;
	LinkNode* S=NULL;
	

        system("pause");
        return 0;

}

单链表的初始化:

因为我们初始化的是一个空链表,只有一个头结点后面没有结点。所以我将头结点的指针域置为空(NULL)

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;
//初始化一个空的单链表
bool Init_LinkList(LinkList* &L){
	L=new LinkNode;
	if(!L){
		printf("内存分配失败!");
		return false;
	}
	L->next=NULL;
	L->date=-1;		//一般来讲,头指针的数据域不进行赋值
	return true;
}

int main(void){
	LinkList* L=NULL;
	LinkNode* S=NULL;
	//初始化一个空的单链表
	if(Init_LinkList(L)){
		printf("初始化一个空的单链表成功!");
	}else{
		printf("初始化一个空的单链表失败!");
	}

	system("pause");
	return 0;
}

使用前前添加法来增加元素(后输入的元素在前面)

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;
//使用前前添加元素(后输入的元素在前面)
bool  insertFront__LinkList(LinkList* &L,LinkNode* &node){

	node->next=L->next;
	L->next=node;
	return true;

	}
//单链表的遍历(这个函数的功能是打印表中每一元素的值(头结点不打印,在后面我就不写了!))
void  Printf_LinkList(LinkList* &L){
	if(!L){
		printf("单链表为空!");
		return ;
	}
	LinkNode* p=NULL;
	p=L->next;
	while(p){
		printf("%d\t",p->date);
		p=p->next;
	}
	
}
int main(void){
	LinkList* L=NULL;
	LinkNode* S=NULL;

	int n,v;

	//使用前插法来增加元素
	printf("请输入要插入元素的个数n:");
	scanf("%d",&n);
	while(n){

	S=new LinkNode;
	printf("请输入要插入元素值v:");
	scanf("%d",&v);
	S->date=v;
	insertFront__LinkList(L,S);
	n--;
	}
	Printf_LinkList(L);

	system("pause");
	return 0;
}

使用尾尾添加法来添加元素

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;

//使用尾插法来添加元素
bool  insertBack__LinkList(LinkList* &L,LinkNode* &node){
	
	LinkList* temp=NULL;    //创建一个LinkList*类型的空链表
	temp=L;                //将我们要进行添加元素的链表(L)赋值给这个空链表
	/*利用这个while循环使每一次
        循环结束后temp为单链表L的最后一个结点*/
	while(temp->next){

	temp=temp->next;

	}
        //此时temp已经为单链表L的最后一个结点
        //将temp结点的指针域中保存的地址改为指向新生成的结点
	temp->next=node;
        //然后将新生成的结点的指针域中保存的地址置为空(NULL)
	node->next=NULL;
	//添加成功,返回true;
	return true;
}
int main(void){
	LinkList* L=NULL;
	LinkNode* S=NULL;

	int n,v;

	//使用尾插法来增加元素
	printf("请输入要插入元素的个数n:");
	scanf("%d",&n);
	while(n){
        //生成要添加的结点
	S=new LinkNode;
	printf("请输入要插入元素值v:");
	scanf("%d",&v);
        //赋值我就直接在main函数中赋了
	S->date=v;
	insertBack__LinkList(L,S);
	n--;
	}
	Printf_LinkList(L);

	system("pause");
	return 0;
}

在任意位置插入元素 

 

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;

//在单链表的任意位置插入元素
bool  insertShuiYi__LinkList(LinkList* &L,int &e,int n){
        //定义一个变量j,用于退出后面的while循环
	int j;
        /*因为我们要找到插入位置的前一个结点,并且不能直接通过链表L来遍历,否则会破环
        链表L的原有结构,所以我定义了两个LinkList*类型的指针*/
	LinkList *p,*s;
        //将L赋值给P
	p=L;
	j=0;
	while(p&&j<n-1){
        /*这里第一次循环的时候,y因为P=L所以p->next指向的是链表L的第一个节点
        第二次循环的时候则指向第二个节点,以此类推。此处觉得难理解的朋友可以画张图模拟一下*/
		p=p->next;
		j++;
	}
        /*那么经过上面的while循环之后,p就是单链表L中我们要插入结点的上一个结点了,
        但是假如我们输入的位置不合法呢,是不是应该检查一下我们的输入不合法,所以我用下面的if语句 
         来进行合法性检查*/
	if(!p||j>n-1){
		return false;
	}
        /*到此处就说明我们的输入是合法的,并且要插入结点的上一个结点我们也得到了(就是P),接下来                                                   我给s分配了LinkNode类型大小的内存(s就是我们要插入的节点)*/
	s=new LinkNode;
     //给要插入的结点赋值
	s->date=e;
       //让新生成的结点的指针域保存的是要插入结点的上一个结点的指针域保存的地址
	s->next=p->next;
        //让我们要插入结点的上一个节点的指针域保存的是指向我们要插入结点的地址
	p->next=s;
        //插入成功,返回!
	return true;
}

int main(void){
	LinkList* L=NULL;
	LinkNode* S=NULL;

	int n,v,n1,v1;

	//在单链表的任意位置插入元素
	printf("请输入要插入要插入的值v1和位置n1[用空隔开]:");
	scanf("%d\t%d",&v1,&n1);
	S=new LinkNode;
	S->date=v1;
	if(insertShuiYi__LinkList(L,S->date,n1)){
		printf("插入成功!");
	}else{
		printf("插入失败!");
	}
	Printf_LinkList(L);

	system("pause");
	return 0;
}

删除指定位置的元素 

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;

bool  delete__LinkList(LinkList* &L,int n){

	LinkList * p,*q;
	p=L;
	int index=0;
	if(!L||!L->next){
		return false;
	}
        /*通过while循环来找到要删除的结点的上一个结点*/
	while((p->next)&&(index<n-1)){
		p=p->next;
		index++;
	}
        /*检查我们要删除结点是否存在*/
	if(!p->next||(index>n-1)){
		return false;
	}
        /*到此处就说明要删除节点是存在的,并且通过上面的while循环我们呢已经找到了要删除的节点的上一个结点p*/
        /*现在我们就可以进行删除操作了,
        首先我们用q来保存我们即将要删除的结点;p是我们要删除的节点的上一个节点,那么p->next就是指向下一个节点,也就是我们要删除的节点*/
	q=p->next;
        /*现在我们就将我们要删除的上一个结点的指针域中保存的地址改为我们要删除节点的下一个节点的    地址*/
	p->next=q->next;
        /"将我们要删除结点占用的内存释放掉!"/
	delete q;
        /"删除操作成功!返回!"/
	return true;
}
int main(void){
	LinkList* L=NULL;
	LinkNode* S=NULL;

	int n,v,n1,v1,n2;

	
	//删除指定位置的元素
	printf("请输入要删除的元素位置n2:");
	scanf("%d",&n2);
	delete__LinkList(L,n2);

	Printf_LinkList(L);


	system("pause");
	return 0;
}

单链表的查找(这个大家就领悟一下咯!原理和上面的一样的!)

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;
//查找元素(按值查找)
bool findValue__LinkList(LinkList* &L,int v3){
	
	if(!L) return false;
	LinkList* temp=NULL;
	temp=L;
	int i=0,j=0;
	while(temp){

		if(temp->date==v3){
			printf("元素出现在第:\t%d个位置\n",i);
			j++;
		}
		temp=temp->next;
		i++;
	}
	if(j==0){
		printf("你查找的元素不存在!\n");
	}
	return true;
}
int main(void){
	LinkList* L=NULL;
	LinkNode* S=NULL;

	int n,v,n1,v1,n2,v3;

	
	//单链表的查找,结果要返回元素的位置(按值查找)
	printf("请输入要查找元素的值的v3:");
	scanf("%d",&v3);
	if(findValue__LinkList(L,v3)){
			printf("查找操作成功!");
	}else{
		printf("查找操作失败!");
	}


	system("pause");
	return 0;
}

单链表的销毁(这个大家就领悟一下咯!原理和上面的一样的!)

#include<stdio.h>
#include<iostream>

typedef  struct _LinkList{
	
	int date;				//数据域
	struct _LinkList *next;	//指针域

}LinkList,LinkNode;

//单链表的销毁
bool destory__LinkList(LinkList* &L){
	if(!L) return false;
	LinkList* temp=L;
	while(temp){
		L=L->next;
		delete temp;
		temp=L;
	}
	return true;
}
int main(void){
	
	//单链表的销毁
	destory__LinkList(L);
	Printf_LinkList(L);
	system("pause");
	return 0;
}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用C语言实现的链表原地逆转的代码: ```c #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* next; }; void reverseList(struct Node** head) { struct Node* prev = NULL; struct Node* current = *head; struct Node* next = NULL; while (current != NULL) { next = current->next; current->next = prev; prev = current; current = next; } *head = prev; } void printList(struct Node* head) { while (head != NULL) { printf("%d ", head->data); head = head->next; } printf("\n"); } void push(struct Node** headRef, int newData) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = newData; newNode->next = *headRef; *headRef = newNode; } int main() { struct Node* head = NULL; push(&head, 3); push(&head, 2); push(&head, 1); printf("Original list: "); printList(head); reverseList(&head); printf("Reversed list: "); printList(head); return 0; } ``` 在上述代码中,我们首先定义了一个 `Node` 结构体来表示链表中的每个节点,包括节点的值和指向下一个节点的指针。然后我们定义了 `reverseList` 函数来实现原地逆转链表的功能。该函数接受一个指向指针的指针 `head`,这是因为我们需要通过指针来修改链表的头节点,所以我们传递指向指针的指针。在函数内部,我们使用三个指针 `prev`、`current` 和 `next` 来依次遍历链表,并将每个节点的指针指向前一个节点,从而实现原地逆转链表的目的。 最后,我们定义了一个 `push` 函数来添加新节点到链表的头部,并定义了 `printList` 函数来打印链表中所有节点的值。在 `main` 函数中,我们创建了一个包含三个节点的链表,并调用 `reverseList` 函数来原地逆转该链表,最后打印出原始和逆转后的链表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值