单链表基本操作总结

链表基本概念:
链表:线性表的链式存储。
数据域:存储数据信息。即数据。
指针域:存放下一节点的位置信息。即该指针指向下一节点。

单链表:每一个节点node:一个数据域 + 一个指针域。
头节点:
1、数据域可以存放线性表长度等公共信息。
2、指针域,指向第一个节点(数据域)的位置。
3、头结点不一定是链表的必须元素。不过有了头结点,对第一个元素节点前插入和删除元素,就和其它节点一致了。
4、头结点是为了操作的同一和方便设立的,其数据域一般无意义,也可存放链表长度。
头指针:指向第一个结点的指针。
最后一个节点:数据域存放数据;指针域为空,即NULL。
若线性表为空,则头节点的指针域为空。
// 循环链表:将单链表中的终端节点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表简称循环链表。
// 双向链表:是在单链表的每个节点中,再设置一个指向其前驱节点的指针域

单链表基本操作有:创建、输出、测长、插入、删除、逆置、排序等。

单链表结构定义代码:

typedef struct Node{
    int data;
    struct Node *next;
}ListNode;

创建单链表操作:

/**创建链表*/
ListNode * Create_list(int n)     // 注意这里函数返回值为一个指向Node的指针,n表示几个节点
{
    int elem,i;
    i = 1;
    ListNode *head, *current, *temp;   /*current:代表一个当前节点,它的下一节点是你正要创建的;temp:代表你正要创建的节点。*/
    head = new ListNode;
    head->next = NULL;
    head->data = n;
    current = head;

    while(i <= n)   /*尾插法:即新节点放在尾部*/
    {
        cout << "please input elem: " << endl;
        cin >> elem;

        temp = new ListNode;
        temp->data = elem;
        temp->next = NULL;
        current->next = temp;
        current = temp;
        i++;
    }

    return head;
}

输出操作:

/**输出链表*/
int Output_list(ListNode *head)
{
    ListNode *p;
    p = head->next;
    if(p == NULL)
    {
        cout << "The List is NULL" << endl;
        return 0;
    }
    do{
        cout << p->data << ' ';
        p = p->next;
    }while(p != NULL);           // 这里需要加“;”

    cout << endl;

    return 0;
}

测一个链表的节点数,即长度:

/**测长度*/
int Length_test(ListNode *head)
{
    ListNode *p;
    int i = 0;
    p = head->next;

    while(p != NULL)
    {
        i++;
        p = p->next;
    }
    cout << "The length of list is " << i << endl;
    return 0;
}

插入节点操作:

/**在第i个节点后插入一个节点,elem:表示你要插入的数据*/
ListNode * Insert_node(ListNode *head,int elem,int i)
{
    int j = 0;
    ListNode *p,*temp;
    temp = head->next;
    /*错误写法
    while(NULL != temp) 在找到 j 后没有跳出循环
    {
        j++;
        if(j <= i)
            temp = temp->next;
    }
    */
    while(NULL != temp)
    {
        j++;
        if(j >= i)   /**指针停在第i个节点之前*/
            break;
        temp = temp->next;
    }
    if(temp == NULL)
    {
        cout << "There is no i" << endl;
        return head;
    }
    p = new ListNode;
    p->data = elem;
    p->next = temp->next;
    temp->next = p;

    head->data = head->data + 1;   /**插入一个结点,头结点数据保存的链表长加一*/

    return head;
}

删除操作:

/**删除第i个结点*/
ListNode * Delete_node(ListNode *head,int i)
{
    int j = 0;
    ListNode *temp,*pre_temp;
    temp = head->next;

    while(NULL != temp)
    {
        j++;
        if(j >= i)
            break;
        pre_temp = temp; /**保存之前节点*/
        temp = temp->next;
    }
    if(temp == NULL)
    {
        cout << "There is no i" << endl;
        return head;
    }
    pre_temp->next = temp->next;
    /**这里不能写成temp = temp->next; 因为下面有 delete temp;会将后面的节点删掉*/

    delete temp;

    head->data -= 1;   /**删掉一个结点,头结点数据保存的链表长减一*/

    return head;
}

逆置操作:

/**单链表逆置,将头结点后的节点一个个断开,使用头插法插入在头结点后*/
ListNode * Reverse_list(ListNode *head)
{
    if(NULL == head)
        return head;
    if(NULL == head->next)
        return head;
    if(NULL == head->next->next)
        return head;
    /**要实现逆置,除了头结点外,至少需要2个数据节点*/

    ListNode *curr, *temp;
    curr = head->next;    /**curr用来保存断开后的那一串*/
    head->next = NULL;    /**头结点与后面结点断开*/

    while(NULL != curr)
    {
        temp = curr->next;         /**temp起临时代替curr的作用*/
        curr->next = head->next;   /**头插法*/
        head->next = curr;
        curr = temp;               /**temp将功能还给curr*/
    }
    return head;
}

单链表排序(使用冒泡排序法):此排序算法,仅交换了数据,没有交换结点

void Swap_data(int &a,int &b)   /**这里必须要加引用符,不然交换没效果*/
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
ListNode * Sort_list(ListNode *head)
{
    int i,len;
    ListNode *p;
    len = head->data;
    p = head->next;
    if(NULL == p)
        cout << "list is null" << endl;
    for(i = 1; i <= len; i++)
    {
        while(NULL != p->next)
        {
            if(p->data > p->next->data)
                Swap_data(p->data,p->next->data);
            p = p->next;
        }
        p = head->next;
    }
    return head;
}

一个特别的函数:用于找出单链表中间节点,在不知道节点总数的情况下

/**不知节点总数,只遍历一次就可以求出中间结点*/
/**这个函数有问题,只能对节点为奇数的求解,节点为偶数时,会出现p->next->next无意义的情况,使程序发生错误*/
/*原理是:找两个指针,一个每次走一步,另一个每次走两步,当走两步的指针到结尾时,走一步的指针刚好走到中间结点处*/
void Search_mid(ListNode *head)
{
    ListNode *p_1,*q_2;
    ListNode *mid;
    p_1 = head->next;
    q_2 = head->next;
    while(NULL != q_2->next)
    {
        p_1 = p_1->next;
        q_2 = q_2->next->next;
        mid = p_1;
    }
    cout << "中间值为: " << mid->data << endl;
}

测试主函数:

int main()
{
    ListNode *p;
    int a=3;
    int b = 4;
    p = Create_list(5);
    cout << "The list is:" << endl;
    Output_list(p);
    Length_test(p);

    p = Insert_node(p,6,5);
    cout << "插入节点后:" << endl;
    Output_list(p);
    cout << "New length: " << p->data << endl;

    p = Delete_node(p,3);
    cout << "删除节点后:" << endl;
    Output_list(p);

    p = Reverse_list(p);
    cout << "逆置后:" << endl;
    Output_list(p);

    p = Sort_list(p);
    cout << "排序后(从小到大):" << endl;
    Output_list(p);

    cout << "原ab: " << a << b << endl;
    Swap_data(a,b);
    cout << "交换后: " << a << b << endl;

    Search_mid(p);

    return 0;
}

/点滴积累,我的一小步O(∩_∩)O~/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值