线性表之链表

本文介绍了链表的基本操作,包括初始化链表、使用头插法创建倒序链表、遍历链表、插入节点、按位置删除节点、删除特定值的节点、计算链表长度、获取指定位置节点、排序链表以及合并两个已排序的链表。此外,还提供了找到链表中倒数第k个节点和合并两个链表的解决方案。
摘要由CSDN通过智能技术生成

#include<stdlib.h>

struct LNode{

int data;

LNode *next;

};

//初始化链表

void initlist(LNode *&l)

{

l=(LNode*)malloc(sizeof(LNode));

    l->next=NULL;

}

/*

//创建链表(尾插法) 正序

void creat(LNode *l)

{

LNode *p,*q;

q=l;

p=new LNode();

scanf("%d",&p->data);

while(p->data!=-1)

{

p->next=NULL;

q->next=p;

q=p;

p=new LNode();

    scanf("%d",&p->data);

}

}

*/

//创建链表(头插法)倒序

void creat(LNode *l)

{

LNode *p,*q;

q=l;

p=new LNode();

scanf("%d",&p->data);

while(p->data!=-1)

{

p->next=q->next;

q->next=p;

p=new LNode();

    scanf("%d",&p->data);

}

 }

//遍历链表

void traver(LNode *l)

{

LNode *p;

p=l->next;

while(p!=NULL)

{

printf("%d ",p->data);

p=p->next;

}

}

//链表的插入

void insert(LNode *&l,int x,int pos)

{

LNode *p,*q;

p=l;

int i=1;

while(p!=NULL&&i<pos)

{

p=p->next;

i++;

}

q=new LNode();

q->data=x;

q->next=p->next;

p->next=q;

 }

 //单链表的删除(给定位置的节点)

 void Delete(LNode *&l,int pos)

 {

  int i=0;

   LNode *p,*q;

   p=l->next;

   while(p!=NULL&&i<pos)

   {

    p=p->next;

    i++;

   }

   p->next=p->next->next;

 }

 //删除单链表中所有值为data的节点

 void Delete1(LNode *&l,int x)

 {

  LNode *p,*q;

  q=l;

  p=q->next;

  while(p!=NULL)

  {

    if(p->data==x)

   {

    q->next=p->next;

    free(p);

    p=q->next;

   }

else

{

p=p->next;

q=q->next;

}

 }

}

//返回单链表的长度

int lenth(LNode *l)

{

LNode *p;

int i=0;

p=l;

while(p!=NULL)

{

p=p->next;

i++;

}

return i-1;

 }

 //返回指定节点位置

int getpos(LNode *l,int pos)

{

LNode *p;

p=l;

int i=1;

while(p!=NULL&&i<=pos)

{

p=p->next;

i++;

}

return p->data;

 }

//对单链表从大到小进行排序

void sort(LNode *l)

{

LNode *p;

int i,j,t;

int len=lenth(l);

p=l;

for(i=0;i<len-1;i++)

{

p=l;

for(j=i;j<len-1;j++)

{

if(p->data<p->next->data)

{

t=p->data;

p->data=p->next->data;

p->next->data=t;

}

p=p->next;

}

}

 }

//有序链表的合并

void hebing(LNode *&l1,LNode *&l2)

{

LNode *l,*p,*p1,*p2,*q;

l=new LNode();

l->next=NULL;

p=l;

p1=l1->next;

p2=l2->next;

while(p1!=NULL&&p2!=NULL)

{

   if((p1->data)<(p2->data))

   {

    p->next=p1;

p=p->next;

p1=p1->next;   

   }

   else

   {

    p->next=p2;

p=p->next;

p2=p2->next;       

   }

}

if(p1==NULL)

{

p->next=p2;

}

else if(p2==NULL)

{

p->next=p1;

}

q=l->next;

while(q!=NULL)

{

printf("%d ",q->data);

q=q->next;

}

}

int main()

{

int m,n,a;

LNode *t;

initlist(t);

creat(t);

traver(t);

printf("\n");

scanf("%d %d",&m,&n);

insert(t,m,n);

traver(t);

scanf("%d",&a);

Delete1(t,a);

traver(t);

printf("\n");

printf("%d",lenth(t));

printf("\n");

printf("%d",getpos(t,a));

sort(t);

traver(t);

return 0;

}

链表:

【1】链表中倒数第K个 结点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2.

返回链表 4->5.

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* getKthFromEnd(struct ListNode* head, int k){
        struct ListNode *p,*q;
        int l = 0,t,i = 0;
        p = head;
        q = head;
        while(p){
            l++;
            p = p ->next;
        }
        t = l - k + 1;
        while(q){
            i++;
            if(i == t) break;
            q= q->next;
        }
        return q;
}

【2】合并两个链表

给你两个链表 list1 和 list2 ,它们包含的元素分别为 n 个和 m 个。

请你将 list1 中下标从 a 到 b 的全部节点都删除,并将list2 接在被删除节点的位置。

下图中蓝色边和节点展示了操作后的结果:

1.找到链表1的第a-1个节点
2.找到链表1的第b+1个节点
3.找到链表2的尾节点
4.将链表2插入到链表1的第a个和第b个节点之间

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeInBetween(struct ListNode* list1, int a, int b, struct ListNode* list2){
        struct ListNode *p,*q,*t;
        int k = 0, l = 0;
        p = list1;
        q = list1;
        t = list2;
        while(p){
            k++;
            if(k == a) break;
            p = p ->next;
        }
        while(q){
            l++;
            if(l == b + 1) break;
            q = q->next;
        }
        q = q->next;
        while(t->next){
            t = t->next;
        }
        //t = t->next;
        p->next = list2;
        t->next = q;

        return list1;

}

【3】反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

头插法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


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

【4】合并两个排序的链表

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例1:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
        struct ListNode *p,*q,*t;
        struct ListNode *l = (struct ListNode *)malloc(sizeof(struct ListNode));
        p = l1; 
        q = l2;
        t = l;
        while(p && q){
            if(p -> val < q -> val){
                t -> next = p;
                p = p -> next; 
            }else{
                t -> next = q;
                q = q -> next;
            }
            t = t -> next;
        }
        t -> next = p ? p : q;
        return l -> next;
}

【5】奇偶链表

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。

请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。

你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* oddEvenList(struct ListNode* head){
    if (!head || !head->next) return head;
        //odd--奇数  even--偶数
        struct ListNode *odd,*even,*odd_end,*even_end,*p;
        even = head;
        even_end =head;
        odd= head -> next;
        odd_end = head -> next;
        /*
        奇数结点指向第一个结点,偶数结点指向第二个结点
        移动奇数结点到偶数结点的下一个
        偶数结点移动到奇数结点的下一个
        最后连接到一起
        */

        while(odd_end -> next && even_end -> next){
            odd_end -> next = even_end -> next;
            odd_end = odd_end -> next;
            even_end -> next = odd_end -> next;
            even_end = even_end -> next;
        }
        odd_end -> next = even_end;
        return odd;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值