链表的五种操作

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_44865905/article/details/101106935

单链表翻转:

采用就地逆置, 定义三个指针变量, 一个标记现在跟在head后的节点, 一个记录现在要移动的节点, 一个记录现在要移动的节点之后的节点。

struct ListNode* reverseList(struct ListNode* head){
   	struct ListNode *p, *q, *r;
    p = q = r = (struct ListNode *)malloc(sizeof(struct ListNode));
	if (head == NULL){
		return head;
	}
	if (head->next == NULL) {
		return head;
	}
	p = head;
	q = p->next; 
	r = q->next;
	p->next = NULL;

	while(1) {
		q->next = p;
		head = q;
		if (r == NULL) {
			break;
		}
		p = q; 
		q = r;
		r = r->next;
		
	}
	return head;
}

判断循环链表:

定义两个指针,快慢指针, 快的一次走两个, 慢的一次走一个, 如果他们可以相遇, 说明是循环链表, 如果快指针走到了结尾, 则不是循环链表

bool hasCycle(struct ListNode *head) {
    struct ListNode *pfast, *pslow;
	pfast = pslow = (struct ListNode *)malloc(sizeof(struct ListNode));
	if ((head == NULL) || (head->next == NULL)){
		printf("false");
		return 0;
	}
	pfast = head->next;
	pslow = head;
	while (1) {
		if (pfast->next == NULL) {
            printf("false");
			 return 0;
		} 
		if (pfast->next->next == NULL) {
             printf("false");
			 return 0;
		} 
		
		pfast = pfast->next->next;
		
		pslow = pslow->next;
		if (pslow == pfast) {
            printf("ture");
			return 1;
		}
	}
}

删除倒数第n个节点

使用两次遍历, 方法显而易见,但如果使用一次遍历, 方法是定义两个指针, 第一个指针先向前走n个, 此时第二个指针开始走, 这样当第一个指针走到结尾时, 第二个指针走到倒数第n个节点位置。

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode *ptemp1, *ptemp2, *ppre;
    int i;
    ppre = ptemp1 = ptemp2 = (struct ListNode*)malloc(sizeof(struct ListNode));
    ptemp1 = head;
    ptemp2 = head;
    for (i = 1; i < n; i++) {
        if (ptemp1->next == NULL) {
           return 0;
        }
        ptemp1 = ptemp1->next;
    }
    if (ptemp1->next == NULL) {
        head = head->next;
        return head;
    }
    while(ptemp1->next != NULL) {
        ptemp1 = ptemp1->next;
        ppre = ptemp2;
        ptemp2 = ptemp2->next;
    }
    ppre->next = ptemp2->next;
    return head;
}

单链表找中间节点

定义两个快慢指针, 比如只有三个节点, 快指针指向第三个, 慢指针指向第一个节点, 判断快的下一个是否为空, 此时为空, 让慢指针下一个为头指针, 输出该链表。

struct ListNode* middleNode(struct ListNode* head){
    struct ListNode *pfast, *pslow;
    int i;
    if (head->next == NULL) {
        return head;
    } 
    if (head->next->next == NULL) {
        return head->next;
    }
    pfast = pslow = (struct ListNode*)malloc(sizeof(struct ListNode));
    pfast = head->next->next;
    pslow = head;
    for (i = 1; ; i++){
        if (pfast->next == NULL) {
            head = pslow->next;
            return head;
        }
        if ((pfast->next != NULL) && (pfast->next->next == NULL)) {
            head = pslow->next->next;
            return head;
        }
        
        pfast = pfast->next->next;
        
        pslow = pslow->next;
    }
}

两条链表的合并

我的思路是,先寻找以那条链作为主链,比如1,2,3和2,3,4通过比较第一个我觉定以第一条作为主链,把第二条插到第一条,ptemp标记第二条目前要插入的元素,ppre标记第一条链的元素,如果是1表示插到1后


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    struct ListNode *ppre, *plater, *ptemp;
	int flag = 0;
    if (l1 == NULL) {
        return l2;
    }
    if (l2 == NULL) {
        return l1;
    }
	ppre = plater = ptemp = (struct ListNode *)malloc(sizeof(struct ListNode));
    if (l1->val < l2->val) {
        ppre = l1;
        ptemp = l2;
        while (1) {
            if (ppre->next == NULL) {
                ppre->next = ptemp;
                return l1;
            } else {
                while ((ppre->next != NULL) && (ppre->next->val < ptemp->val)) {
                    ppre = ppre->next;
                }
                if (ppre->next == NULL) {
                    ppre->next = ptemp;
                    return l1;
                } else {
                    if (ptemp->next == NULL) {
                        ptemp->next = ppre->next;                
                        ppre->next = ptemp;
                        return l1;
                    } else {
                        plater = ptemp->next;
                        ptemp->next = ppre->next;
                        ppre->next = ptemp;
                        ppre = ptemp;
                        ptemp = plater;
                    }
                }
            }
        }
    } else {
        ppre = l2;
        ptemp = l1;
        while (1) {
            if (ppre->next == NULL) {
                ppre->next = ptemp;
                return l2;
            } else {
                while ((ppre->next != NULL) && (ppre->next->val < ptemp->val)) {
                    ppre = ppre->next;
                }
                if (ppre->next == NULL) {
                    ppre->next = ptemp;
                    return l2;
                } else {
                    if (ptemp->next == NULL) {
                        ptemp->next = ppre->next;                
                        ppre->next = ptemp;
                        return l2;
                    } else {
                        plater = ptemp->next;
                        ptemp->next = ppre->next;
                        ppre->next = ptemp;
                        ppre = ptemp;
                        ptemp = plater;
                    }
                }
            }
        }
    }
}

这些都是我在力扣上提交的代码

猜你喜欢

转载自blog.csdn.net/qq_44865905/article/details/101106935