链表及其基本操作

链表(linked list):

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

链式存储

链式存储结构特点:
1.用任意一组存储单元存储线性表中的数据元素;
2.这组存储单元可以数连续的也可以是不连续的;
3.每个数据元素除了存储数据外,还要存储前驱、后继元素的地址。

单链表
n个节点按链式存储结构存储,每个节点只包含一个指针域。

单链表
 

线性表的单链表存储结构 

typedef int DataType;  //定义数据元素类型为整型 
typedef struct Node{
	DateType data;     //数据域 
	struct Node *next; //指针域 
}Node;

 

基本操作:

1.获取指定位置的元素

Node* getptr(Node* head, int pos){
	Node *p = head;
	if(p == NULL || pos ==0)     //链表为空或获取链表的第一个节点 
	   return head;
	for(int i=0; p&&i<pos; i++)  //p不为零时,i从0开始循环查找 
	   p = p->next;
	return p;
} 

2.获取单链表中的节点个数

int getSize(Node* head){
	int size = 0;
	Node* p = head;
	while(p){
		size++;
		p = p->next;
	}
	return size;
} 

3.单链表插入(空表、头部)

bool insert(Node** head, int position, DateType d){
	//空表 、插入位置不合理 
	if(position<0 || position>getSize(*head))
	   return false;
	Node *node = (Node*)malloc(sizeof(Node));//分配存储空间 
	node->data = d;       //数据域等于d 
	node->next = NULL;    //指针域为空 
	//头部 
	if(position == 0)
	{
		node->next = *head;
		*head = node;
		return true;
	} 
	//中间或尾部 
	Node *p = getptr(*head, position-1);
	Node* r = p->next;
	node->next = r;
	p->next = node;
	return true;
} 

//用法举例:insert(&head, 1, 10); 

4.单链表删除(头结点)

bool erase(Node** head, int pos){
	//空表 、删除位置不合理 
	if(pos<0 || pos>= getSize(*head))
	   return false;
	Node *p = *head;
	//头结点 
	if(pos == 0){
		*head = (*head)->next;
		free(p);
		p = NULL;
		return true;
	}
	//中间或尾部 
	p = getptr(*head, pos-1);
	Node *q = p->next;
	p->next = q->next;
	free(q);
	q = NULL;
	return true;
} 

//用法举例: erase(&head, 1);

5.将两个线性链表合并

void union(Node *a, Node *b){
	Node *p = a;
	while(p->next)
	    p->next;
	p->next = b;
} 

6.将线性表倒置

void reverse(Node **head){
	Node *p = *head;
	Node *q = p->next;
	if(q == NULL)
	   return;
	Node *r = q->next;
	if(p == *head)
	   p->next = NULL;
	while(true){
		q->next = p;
		if(r == NULL){
			*head = q;
			break;
		}
		else{
			p = q;
			q = r;
			r = r->next;
		}
	}
} 

7.线性表的遍历

void trave(Node *head, void(*fun)(DateType)){
	Node *p = head;
	while(p){
		fun(p->data);
		p = p->next;
	}
} 
void printf(DateType d){
	printf("%d\n", d);
}

 

单循环链表 
循环链表:将单链表中最后一个节点的指针域由空改为指向第一个节点,使整个单链表形成一个环。


 

线性表单循环链表存储结构:

typedef int DataType;
typedef struct Node{
	Datatype data;
	struct Node *next;
}Node;

基本操作:

1.获取单循环链表中的节点个数 

int getSize(Node* rear){
	int size = 0;
	if(rear){                   //rear为尾指针 
		Node* p = rear->next;
		while(p != rear){
		    size++;
		    p = p->next;
	    }
	    size++;
	}
	return size;
} 

2.获取指定位置的元素

 Node* getptr(Node* rear, int pos){
	if(rear == NULL)     
	   return rear;
	if(pos >= getSize(rear))
	   return NULL;
	Node *p = rear->next;
	for(int i=0; i<pos; i++)  //p不为零时,i从0开始循环查找 
	   p = p->next;
	return p;
} 

3.单循环链表插入(空结点、头结点)

bool insert(Node** rear, int position, DateType d){
	if(position<0 || position>getSize(*rear))
	   return false;
	Node *node = (Node*)malloc(sizeof(Node));//分配存储空间 
	node->data = d;       //数据域等于d 
	node->next = NULL;    //指针域为空 
	if(position == 0)
	{
		if(*rear == NULL){
			node -> next = node;
			*rear = node;
		}
		else{
			node->next = (*rear)->next;
	    	(*rear)->next = node;
		}
		return true;
	} 
	Node *p = getptr(*head, position-1);
	Node* r = p->next;
	node->next = r;
	p->next = node;
	if(*rear == p)
	    *rear = node;
	return true;
} 

4.单循环链表删除(头结点)

bool erase(Node** rear, int pos){
	if(*rear==NULL || pos<0 || pos>= getSize(*rear))
	   return false;
	Node *p = (*pear)->next;
	//头结点 
	if(pos == 0){
		(*rear)->next = p->next;
		free(p);
		p = NULL;
		return true;
	}
	//中间和尾部 
	p = getptr(*head, pos-1);
	Node *q = p->next;
	p->next = q->next;
	if(q == rear)
	    rear = p;
	free(q);
	q = NULL;
	return true;
} 

 

C++中的链表是一种常见的数据结构,它由多个节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。链表有很多种类型,包括单向链表、双向链表和循环链表等。 以下是链表基本操作: 1. 创建链表节点 链表节点通常由两个部分组成:数据和指向下一个节点的指针。我们可以定义一个结构体来表示节点: ```c++ struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; ``` 这个结构体包含一个整数和一个指向下一个节点的指针,其中构造函数用于初始化节点的值。 2. 插入节点 插入节点是链表中最基本的操作之一。我们可以将新节点插入到链表的任何位置,包括链表的头部、部或中间。 ```c++ void insertNode(ListNode*& head, int val) { ListNode* newNode = new ListNode(val); newNode->next = head; head = newNode; } ``` 这个函数将创建一个新节点并将其插入到链表的头部。 3. 删除节点 删除节点也是链表中最基本的操作之一。我们可以从链表的任何位置删除节点,包括链表的头部、部或中间。 ```c++ void deleteNode(ListNode*& head, int val) { if (head == NULL) return; if (head->val == val) { ListNode* temp = head; head = head->next; delete temp; return; } ListNode* prev = head; ListNode* curr = head->next; while (curr != NULL) { if (curr->val == val) { prev->next = curr->next; delete curr; return; } prev = curr; curr = curr->next; } } ``` 这个函数将从链表中删除具有指定值的节点。 4. 遍历链表 遍历链表是查看链表中节点值的一种方法。 ```c++ void traverseList(ListNode* head) { ListNode* curr = head; while (curr != NULL) { cout << curr->val << " "; curr = curr->next; } } ``` 这个函数将遍历整个链表,并输出每个节点的值。 这些是链表基本操作。在实际的应用程序中,我们可能需要使用更多的操作来实现特定的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值