1.单向链表的创建
typedef struct Node{//定义结构体
int data; // 数据域
struct Node* next; //指针域
}Node;
Node* init_List(int list[], int n){//链表初始化
if(n == 0) return NULL;
Node* head = NULL;
Node* tail = NULL;
for(int i = 0;i < n;i++){
Node* newnode = (Node*)malloc(sizeof(Node));
newnode->data = list[i];
newnode->next = NULL;
if(!head){
head = newnode;
tail = newnode;
}
else{
tail=tail->next = newnode;
}
}
return head;
}
void printlist(Node* head){ //打印链表
Node* temp = head;
while(temp){
printf("%d -> ",temp->data);
temp = temp->next;
}
printf("NULL\n");
}
2.单向链表寻找最值
Node* findMaxNode(Node* head) {//返回单向链表的最大值节点
if (head == NULL) {
printf("链表为空\n");
return NULL;
}
Node *maxNode = head; // 初始最大节点为头节点
Node *current = head->next; // 从第二个节点开始遍历
while (current) {
if (current->data > maxNode->data) {
maxNode = current; // 更新最大节点
}
current = current->next; // 移动到下一个节点
}
return maxNode;
}
3.有序单向链表删除重复元素
如果单向链表是有序的且包含重复值,我们可以利用有序链表的特点来高效地删除所有重复的节点。由于链表是有序的,相同的值一定是连续的,因此只需要遍历一次链表,比较当前节点和下一个节点的值是否相同即可。
(1)删除所有重复节点
版本1:
Node* deleteDuplicates(Node* head){//单向链表有序且含有重复值,删除所有重复值节点
if (head == NULL || head->next == NULL) {
return head; // 链表为空或只有一个节点,直接返回
}
Node *currnode, *prenode;
currnode = head;
while(currnode){
if(currnode->next != NULL &&currnode->data == currnode->next->data){
if(currnode == head){
while(currnode->next != NULL &&currnode->data == currnode->next->data){
prenode = currnode;
currnode = currnode->next;
free(prenode);
}
head = currnode->next;
free(currnode);
currnode = head;
}
else{
while(currnode->next != NULL &&currnode->data == currnode->next->data){
prenode->next = currnode->next;
free(currnode);
currnode=prenode->next;
}
prenode->next = currnode->next;
free(currnode);
currnode=prenode->next;
}
}
else{
prenode = currnode;
currnode = currnode->next;
}
}
return head;
}
版本2(对版本1进行了逻辑优化):
Node* deleteDuplicates(Node* head) {//单向链表有序且含有重复值,删除所有重复值节点--plus
if (head == NULL || head->next == NULL) {
return head; // 链表为空或只有一个节点,直接返回
}
Node *currnode = head;
Node *prenode = NULL;
while (currnode) {
bool isDuplicate = false;
// 检查当前节点与下一个节点是否有相同值
while (currnode->next != NULL && currnode->data == currnode->next->data) {
isDuplicate = true;
Node *temp = currnode->next;
currnode->next = temp->next; // 跳过重复的节点
free(temp); // 释放重复节点
}
if (isDuplicate) {
// 如果当前节点也是重复的,删除当前节点
Node *temp = currnode;
if (prenode == NULL) {
// 如果重复的是头节点
head = currnode->next;
} else {
prenode->next = currnode->next; // 跳过当前重复节点
}
currnode = currnode->next;
free(temp);
} else {
// 当前节点不是重复节点,继续前进
prenode = currnode;
currnode = currnode->next;
}
}
return head;
}
示例:
int main(void)
{
int list[] = {1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 7, 7};
int n = sizeof(list)/sizeof(list[0]);
Node *head = init_List(list, n);
printlist(head);
head = deleteDuplicates(head);
printlist(head);
}
结果为:1 -> 1 -> 2 -> 3 -> 3 -> 3 -> 4 -> 5 -> 5 -> 6 -> 7 -> 7 -> NULL
2 -> 4 -> 6 -> NULL
(2)每个重复节点保留一个值
要实现每个重复节点只保留一个值,我们只需要删除重复的节点并保留第一个出现的节点即可。因为链表是有序的,相同值的节点会相邻排列,所以只需要在遍历链表时删除后续的相同节点。
Node* deleteDuplicates_pro(Node* head){
if (head == NULL || head->next == NULL) {
return head; // 链表为空或只有一个节点,直接返回
}
Node *currnode = head;
while (currnode != NULL && currnode->next != NULL) {
// 如果当前节点与下一个节点的值相同
if (currnode->data == currnode->next->data) {
Node *temp = currnode->next; // 临时保存要删除的节点
currnode->next = temp->next; // 跳过下一个节点
free(temp); // 释放内存
} else {
// 如果值不同,继续往下走
currnode = currnode->next;
}
}
return head;
}
4.合并两个有序链表
Node* mergeTwoLists(Node* l1, Node* l2) {
if (l1 == NULL) return l2;
if (l2 == NULL) return l1;
Node* head = NULL; // 合并后链表的头节点
Node* tail = NULL; // 合并链表尾节点
// 初始化合并后的头节点
if (l1->data <= l2->data) {
head = l1;
l1 = l1->next;
} else {
head = l2;
l2 = l2->next;
}
tail = head; // 头节点也是尾节点的初始值
// 合并两个链表
while (l1 != NULL && l2 != NULL) {
if (l1->data <= l2->data) {
tail->next = l1;
l1 = l1->next;
} else {
tail->next = l2;
l2 = l2->next;
}
tail = tail->next; // 移动到下一个节点
}
// 连接剩余部分
if (l1 != NULL) {
tail->next = l1;
} else {
tail->next = l2;
}
return head;
}