码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构--单链表

时间:2016-05-12 15:18:54      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

最近复习数据结构,加强下自己的基础。在复习中遇到的问题在这里做下笔记。
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
单链表的定义:

typedef struct LNode{
    int data;               // data 中存在结点的数据域
    struct LNode *next;     // 指向后继结点的指针
}LNode;                     // 定义单链表结点类型

单链表的构造方法(尾插法和头插法)
(1)尾插法

void CreateListR(LNode *&C, int a[], int n){
    LNode *s, *r; //s 用来指向新申请结点, r 始终指向C的终端结点
    int i;
    C = (LNode *)malloc(sizeof(LNode *)); //申请C的头结点空间
    C -> next = NULL;  
    r = C; //r 指向 C 的头结点,因为此时 C 的头结点就是 C 的终端结点
    for (i=0;i<n;i++){
        s = (LNode *)malloc(sizeof(LNode *)); //s指向新申请结点
        s -> data = a[i]; 
        r -> next = s; //r 接纳新结点
        r = r -> next; //r 指向终端结点,以便接纳下一个到来的结点
    }
    r -> next = NULL; //所有元素都装入了链表 C 中,将 C 的终端结点的指针域置为NULL
}

技术分享

(2)头插法

void CreateListH(LNode *&C, int a[], int n){
    LNode *s;
    int i;
    C = (LNode *)malloc(sizeof(LNode *)); //申请C的头结点空间
    C -> next = NULL;
    for (i=0;i<n;i++){
        s = (LNode *)malloc(sizeof(LNode *)); //s指向新申请结点
        s -> data = a[i]; 
        s -> next = C -> next; //s 所指向新结点的指针域 next 指向 C 中的开始结点
        C -> next = s ; //头结点的指针域 next 指向 s 结点, 使得 s 结点成为了新的开始结点
    }
}

技术分享

链表删除( 删除 p->next )

q = p -> next;
p -> next = p -> next -> next;
free(q);

技术分享

链表的插法(头插法和尾插法)和删除是所有链表知识的基础知识,很多操作都是由着三个基本操作组成。

下面介绍一个链表的综合题目(leetCode上面的)
给定两个非负整数(个位整数)的单链表,将两个单链表中对应元素相加的到的值保存到一个单链表中

输入: [2, 4, 3]
[5, 6, 4]
输出: [7, 0 ,8]

题目分析:(根据题目描述和输入输出实例)每个单链表中元素的值相加,如果小于10,则得到的值即为所求的值,如果相加的值大于10,那么所要求的值为个位上的数,同时十位上的1要加到下次运算中。
思想分析:可以创建一个单链表,让其长度为输入链表中最大的长度。因为单链表没有提供length的属性,那么只有通过变量才能得到最大的长度,这样会加大运行的负担,因此在遍历单链表的时候,判断单链表是否为空,如果一个单链表为空,另一个还没有为空,那么为空的那个单链表往后的值可以认为是0,这样就不会影响最终的计算,一次遍历就可以达到最大的长度。需要注意的是,如果遍历完后,最后一次的得到的值大于10,那么需要在最后再添加一个结点,来保存得到的十位数。
代码实现(C++)

#include <iostream>
using namespace std;

// Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

//使用模板定义一个函数getArrayLen,该函数将返回数组array的长度
template <class T>
int getArrayLen(T& array)  {
    return (sizeof(array) / sizeof(array[0]));
}

class Solution {
public:
    /**
     *  用尾插法创建一个没有头结点的链表
     */
    ListNode* createListE(int array[], int n){
        ListNode *r, *s;
        ListNode* list = (ListNode *)malloc(sizeof(ListNode *));
        list->next = NULL;
        r = list;
        for (int i = 0; i < n; ++i) {
            s = (ListNode *)malloc(sizeof(ListNode *));
            s -> val = array[i];
            r -> next = s;
            r = r->next;
        }
        r->next = NULL;
        return list->next;
    }

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {//链表不含头结点
        int flag = 0; //定义标示符,初始化为0,链表值相加大于10为1,否则为0
        ListNode* p = l1;
        ListNode* q = l2;
        ListNode* l3 = (ListNode*)malloc(sizeof(ListNode*)); //申请l3的头结点空间(可以创建带头结点的链表,然后返回l3->next, 去除头结点即可)
        l3 -> next = NULL;
        ListNode* r = l3; //r 指向 l3 的始终最后一个结点

        int valp, valq; //p,q链表对应位置的值
        while (p != NULL || q != NULL){ // 一个不为空,就继续(得到最大的长度)
            valp = (p==NULL?0:p->val); // p为空的话,对应值为0;否则为p链表的值
            valq = (q==NULL?0:q->val);

            ListNode* s = (ListNode*)malloc(sizeof(ListNode*)); //s指向新申请结点
            if (valp + valq + flag < 10){ //小于10的情况
                s -> val = (valp + valq + flag);
                flag = 0; // 小于10设为0,不影响下次的计算
            }else{ //大于10的情况
                s -> val = (valp + valq + flag) % 10; //取个位的值
                flag = 1; // 大于10设为1,下次计算加1
            }
            //链表尾插法
            r -> next = s;
            r = r -> next;

            if (p != NULL) p = p -> next; //p不为空的话,向后移动一个位置
            if (q != NULL) q = q -> next;
        }

        if (flag == 1 ){ //最后一次结果大于10的情况
            ListNode* s = (ListNode*)malloc(sizeof(ListNode*)); //再次申请新结点
            //将新结点用尾插法插入到l3链表中
            s -> val = flag;
            r->next = s;
            r = r->next;
        }
        r -> next = NULL; //所有元素都装入了链表 l3 中,将 l3 的终端结点的指针域置为NULL
        return l3->next; //返回去除头结点的 l3 链表
    }
};

int main(int argc, const char * argv[]) {
    //测试用例
    int a[] = {2,4,3};
    int b[] = {5,6,4};

//    int a[] = {3};
//    int b[] = {7,6};
//
//    int a[] = {5};
//    int b[] = {5};
//
//    int a[] = {3, 8};
//    int b[] = {2};

    //计算数组的长度
    int alength = getArrayLen(a);
    int blength = getArrayLen(b);

    Solution s;
    //尾插法得到无头结点的单链表
    ListNode* l1 = s.createListE(a, alength);
    ListNode* l2 = s.createListE(b, blength);

    //计算两个单链表的和
    ListNode* l3 = s.addTwoNumbers(l1, l2);
    ListNode* r = l3;
    while (r!=NULL) {
        cout<<r->val<<",";
        r = r->next;
    }
    cout<<endl;

    return 0;
}

数据结构--单链表

标签:

原文地址:http://blog.csdn.net/alpaca12/article/details/51365045

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!