主要内容:
一、链表的动态创建(增)
(1)"头插法"动态创建链表
#include <stdio.h>
#include <malloc.h>
struct Node{
int data; //数据域
struct Node *next; //指针域
};
/* 动态创建-头插法(用二级指针保存head指针的地址,就不需要返回值) */
void createLinkedList(struct Node **head,int data){
/* 初始化新结点 */
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
if(*head != NULL){
//非第一个结点
newNode->next = *head; //新结点下一个指向此时的head结点
*head = newNode; //然后,更新head指针位置(此时新结点是head)
}else{
*head = newNode;
}
}
(2)"尾插法"动态创建链表
/* 动态创建链表-尾插法(通过返回值修改(更新)head指针) */
struct Node *createLinkedList(struct Node *head,int data){
/* 初始化新结点 */
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
if(head != NULL){
//newNode不是链表中的第一个结点
struct Node *tail = head;
while (tail->next != NULL){
//找到尾结点
tail = tail -> next;
}
tail -> next = newNode; //让尾结点的下一个指向新结点
}else{
//newNode是链表中的第一个结点
head = newNode; //此时即是头也是尾
}
return head;
二、删除链表的某个结点(删)
删除结点分两种情况:①是删除头结点;②是中间结点(包括尾结点)
/* 删除链表指定元素结点 */
struct Node *deleteNode(struct Node *head,int data){
struct Node *ptmp = head;
if(ptmp->data == data){
//删除头结点:直接让下一个结点成为头,并释放原来的head
head = ptmp -> next;
free(ptmp);
}else{
//删除中间结点:判断下一个结点,让此时的head指向next的next即可
while ( ptmp != NULL){
if( ptmp->next->data == data){
//特别注意:这里查询到了指定的data后,要return
struct Node *p = ptmp->next; //否则出现段错误:原因是下一个可能为NULL
ptmp->next = ptmp->next->next;
free(p);
return head;
}
ptmp = ptmp -> next;
}
}
return head;
}
三、修改链表的某个结点(改)
/* 修改指定元素 */
struct Node *updateNode(struct Node *head,int data,int newData){
struct Node *ptmp = head;
while(ptmp != NULL){
if(ptmp->data == data){
ptmp->data = newData;
}
ptmp = ptmp -> next;
}
return head;
}
四、链表的遍历(查)
/* 遍历 */
void traverLinkedList(struct Node *head){
struct Node *ptmp = head;
while(ptmp != NULL){
printf("%d ",ptmp->data);
ptmp = ptmp -> next;
}
}
五、面试题(待补充)
(1)数组和链表的区别?
数组和链表都属于线性表,数组的存储方式是顺序存储,它在内存中占用的地址空间是连续的,定义出来后空间大小是固定的,虽然读取效率较高但是不利于扩展(想要实现插入数据,修改数据相较于链表困难);链表的存储方式是链式结构,每一个结点的地址空间可以不连续,通过指针连接,每一个结点保存下一个结点的地址,相比于数组扩展方便,操作数据也更容易。