链表常用操作及面试题

链表是一种比较基础的数据结构,虽然在acm比赛中不常用,但是在面试中还是比较常问的,所以拿出来写了一下,发现很多错误,由于操作中用到很多指针,所以不经常写的话很容易写错。

这里写了一下链表的创建,比较基础!
然后是删除链表的元素,需要考虑删除的是否为第一个元素。
然后是找链表的倒数第k个元素,可以用两个指针,一个指针后移k次,然后两个同时向后走,当先走k次的走到尾部的时候,另一个刚好到倒数第k个元素,因为两个指针的位置一直是相差k的。
最后是反转链表,边向后走,边把链表的指针指向前面的元素就可以了。

Notice:
1:链表只有在创建和删除节点的时候需要分配内存,即操作内存的时候需要,这是因为链表分配内存块不是连续的,是离散的,即一个节点一个节点的分配,所以需要调用内存分配函数,内存分配函数常用的有两个
C++中的new和C语言中的malloc这个也是面试常问的,即其区别。
调用方法的话很简单,

ListNode *node = new ListNode();
ListNode *node = (ListNode *)malloc(sizeof(ListNode));

当然别忘了释放内存,其对应的delete和free,写法如下

delete node;
free(node);

它们两个有什么区别呢?
1:now返回指定类型的指针,其可以自动计算所要分配内存的大小。而malloc需要强制转换成实际的类型,并且大小要我们给出来。
2:malloc只管分配内存,不对其值进行初始化,即值为随机的,而new可以初始化

一些练习代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

struct ListNode
{
    int val;
    ListNode * next;
};

ListNode* creat(int n)  //创建链表
{
    ListNode *head  = new ListNode(), *p = new ListNode();
   // head = p = (ListNode *)malloc(sizeof(ListNode));
    scanf("%d",&p->val);
    p->next = NULL;
    head = p;
    for(int i=1;i<n;i++)
    {
        ListNode *tmp = new ListNode();
        //tmp = (ListNode* )malloc(sizeof(ListNode));
        scanf("%d",&tmp->val);
        tmp->next = NULL;
        p->next = tmp;
        p = p->next;  ///notice:指针后移
    }
    return head;
}
void print(ListNode *head)   ///打印链表
{
    while(head!=NULL){
        printf("%d ",head->val);
        head = head->next;
    }
    puts("");
}

ListNode* RemoveNode(ListNode *head,int num)
{
    ListNode *newhead = NULL;  //只有在添加的时候才需要分配内存
    newhead = head;  ///head 指向移动之后newhead和tmp并不跟着移动
    if(newhead->val == num){  ///删除的是头结点的话
        head = head->next;
        return head;
    }
    ListNode *tmp = NULL;
    tmp = head;   //记录找到节点的前一个节点
    while(newhead!=NULL)  //其他节点
    {
        if(newhead->val == num){
            tmp->next = tmp -> next -> next;
            //delete tmp;  不能释放内存
            return head;
        }
        tmp = newhead;
        newhead = newhead->next;
    }
}
void Find_KthNode(ListNode *head,int k)  ///查找倒数第k个元素
{
    ListNode *one = NULL,*two = NULL;
    one = head,two = head;
    while(one!=NULL && k--)
    {
        one = one->next;
    }
    while(one!=NULL)
    {
        one = one->next;
        two = two->next;
    }
    printf("Find last %dth secessful\n");
    printf("%d\n",two->val);
}
ListNode* ReverseList(ListNode *head)
{
    ListNode *p = head;
    ListNode *pre = NULL;
    while(p!=NULL)
    {
        ListNode *tmp = p->next;
        if(tmp==NULL)
            head = p;
        p->next = pre;
        pre = p;
        p = tmp;  ///Notice : 这里写成p = p->next 是错的
    }
    return head;
}

int main()
{
    //freopen("Input.txt","r",stdin);
    int n;
    while(~scanf("%d",&n))
    {
        ListNode *head = creat(n);
        puts("Creat secessful");
        print(head);
        int num;
        scanf("%d",&num);
        head = RemoveNode(head,num);
        puts("ReMove secessful");
        print(head);
        scanf("%d",&num);
        Find_KthNode(head,num);
        head = ReverseList(head);
        //printf("HEAD->%d\n",head->val);
        print(head);
    }
    return 0;
}
/*****
10
1 2 3 4 5 6 7 8 9 10
10
3
******/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值