6.2单链表

1.特征:

链表中的元素个数可以根据需要增加和减少,不像数组,在声明之后就固定不变;
元素的位置可以变化,即可以从某个位置删除,然后再插入到一个新的地方;

2.组成:数据成员和指针存放下一个结点的地址(链表中的各节点在内存的存储地址不是连续的)




3.基本操作:
(1)创建链表是指,从无到有地建立起一个链表,即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系。
(2)检索操作是指,按给定的结点索引号或检索条件,查找某个结点。如果找到指定的结点,则称为检索成功;否则,称为检索失败。
(3)插入操作是指,在结点ki-1与ki之间插入一个新的结点k’,使线性表的长度增1,且ki-1与ki的逻辑关系发生如下变化:插入前,ki-1是ki的前驱,ki是ki-1的后继;插入后,新插入的结点k’成为ki-1的后继、ki的前驱。
(4)删除操作是指,删除结点ki,使线性表的长度减1,且ki-1、ki和ki+1之间的逻辑关系发生如下变化:删除前,ki是ki+1的前驱、ki-1的后继;删除后,ki-1成为ki+1的前驱,ki+1成为ki-1的后继.
(5)打印输出

4.链表结构体定义:struct node { int num; struct node *next; } 

6.结点指针定义:node *p;

7.结点存储空间申请、释放:p = new node;/delete p;

8.种类:链表又分为单链表、双向链表和循环链表

9.创建:

1 ) 定义链表的数据结构。
2 ) 创建一个空表。
3 ) 利用new( )函数向系统申请分配一个节点。
4 ) 将新节点的指针成员赋值为空(保证最后一个元素指针指向NULL)。若是空表,将新节点连接到表头;若是非空表,将新节点接到表尾。
5 ) 判断一下是否有后续节点要接入链表,若有转到3 ),否则结束。


</pre>典型的链表创建、遍历模板:<pre name="code" class="cpp">#include<stdio.h>  
#include<malloc.h>  
struct node  
{  
    int data ;                  //数据域
    struct node *next ;   //指针域,指向下一个结点
};  
int main()  
{  
     int n;   //将要输入的结点的个数
     scanf("%d",&n);
    struct node *head = (struct node *)malloc(sizeof(struct node));   //为头结点申请存储空间
    head->next = NULL;           //现在是空链表,头结点的next为空
    struct  node *tail = head;   //tail是指向链表的最后一个结点
    for(int i = 1;i <= n;i++ )  
    {  
        struct node *p=(struct node *)malloc(sizeof(struct node));  //为新结点申请存储空间
        scanf("%d",&p->data);   //输入新结点的数据
        p->next=head->next;;   //因为要与输入顺序一致,所以每次输入的值为当前链表的第一个结点
        head->next=p;  
            }  
    
    struct node *s=head->next; //将s指向链表的第一个结点
    while(s->next!=NULL)   //判断是否是链表最后一个元素就是要判断该元素的next指针是否为空
    {
        printf("%d ",s->data);  
        s=s->next;   //s移向先一个结点
    }  
    printf("%d\n",s->data); //输出最后一个结点的数据并输出换行
    return 0;  
}  
10.例题:UVA-11988 这个代码会TLE,但是思路对,这是建表的一个好的练习

#include<stdio.h>
#include<time.h>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<iostream>
#include<vector>
using namespace std;
struct node
{
    char n;node *next;
};
int main()
{
    char t[100005];
    while(scanf("%s",t) != EOF)
    {
        node *last = new node;  //创建尾部,
        last->next =NULL;  //指明尾部指针
        node *tou = last;  //创建头部并指明头部指针
        node *lastt = last;
        int len = strlen(t);
        for(int i = 0;i < len;i++)
        {
            if(t[i] == '[')
            {
                last = tou;
                last->next = tou->next;
            }
            else if(t[i] == ']')
            {
                node *temp = last;
                while(temp->next != NULL)
                {
                    temp = temp->next;
                }
                last = temp;
            }
            else
            {
                node *u = new node;  //创建子节点
                if(last->next == NULL)  //接上元素
                    u->next = NULL;
                else  //插入元素
                    u->next = last->next;
                last->next = u;
                u->n = t[i];
                last = u;  //子节点移动
            }
        }
        node *u = tou->next;
        while(1)
        {
            if(u == NULL) break;
            printf("%c",u->n);
            u = u->next;
        }
        printf("\n");
    }
    return 0;
}
以下是刘汝佳的思路:

#include<stdio.h>
#include<iostream>
#include<string>
#include<stack>
#include<string.h>
using namespace std;
int last,cur,next[100005];
char s[100005];
int main()
{
    while(scanf("%s",s+1)!=EOF)
    {
        int len=strlen(s+1);
        last=cur=0;
        next[0]=0;
        for(int i=1;i<=len;i++)
        {
            if(s[i]=='[') cur=0;
            else
            if(s[i]==']') cur=last;
            else
            {
                next[i]=next[cur];
                next[cur]=i;
                if(cur == last) last = i;
                cur = i;
            }
        }
        for(int i=next[0];i!=0;i=next[i])
            printf("%c",s[i]);
        printf("\n");
    }
    return 0;
}

11.STL链表:

定义:list<int(任意类型)> name;

②头文件:#include<list>

③push_back()、push_front():往链表后面/前面填元素

④empty():判断链表是否为空

⑤begin()、end():返回链表的第一、最后一个元素

⑥链表遍历:

#include <iostream>
#include <string>
#include <list>
int main (void)
{
    list<string> Milkshakes;
    list<string>::iterator MilkshakeIterator; //定义迭代器类型
    Milkshakes.push_back("Chocolate");
    Milkshakes.push_back("Strawberry");
    Milkshakes.push_front("Lime");
    Milkshakes.push_front("Vanilla");
    Milkshakes.push_front("The Milkshake Menu");
    Milkshakes.push_back("*** Thats the end ***");
    for (MilkshakeIterator=Milkshakes.begin();MilkshakeIterator!=Milkshakes.end();++MilkshakeIterator)  //遍历链表(访问了链表中的所有元素),注意不包含最后一个元素
    	cout << *MilkshakeIterator << endl;
}

注:这个list容器,就象你所想的,它不支持在iterator加一个数来指向隔一个的对象。 就是说,我们不能用Milkshakes.begin()+2来指向list中的第三个对象,因为STL的list是以双链的list来实现的, 它不支持随机存取。

⑦for_each()遍历:

#include <iostream.h>
#include <string>
#include <list>
#include <algorithm>
 
PrintIt (string& StringToPrint)
{
    cout << StringToPrint << endl;
}
 
int main (void)
{
    list<string> FruitAndVegetables;
    FruitAndVegetables.push_back("carrot");
    FruitAndVegetables.push_back("pumpkin");
    FruitAndVegetables.push_back("potato");
    FruitAndVegetables.push_front("apple");
    FruitAndVegetables.push_front("pineapple");
 
    for_each  (FruitAndVegetables.begin(), FruitAndVegetables.end(), PrintIt);  //最后一个是要做的事(一定要是函数吗?)
}


⑧count():

#include <list>
#include <algorithm>
int main (void)
{
    list<int> Scores;
    Scores.push_back(100);
    Scores.push_back(80);
    Scores.push_back(45);
    Scores.push_back(75);
    Scores.push_back(99);
    Scores.push_back(100);
 
    int NumberOf100Scores(0);
    NumberOf100Scores = count(Scores.begin(), Scores.end(), 100);  //当元素为100时,<span style="font-family: Arial, Helvetica, sans-serif;">NumberOf100Scores自增</span>
    cout << "There were " << NumberOf100Scores << " scores of 100" << endl;
}

count_if():

find():

#include <string>
#include <list>
#include <algorithm>
int main (void)
{
    list<string> Fruit;
    list<string>::iterator FruitIterator;
    Fruit.push_back("Apple");
    Fruit.push_back("Pineapple");
    Fruit.push_back("Star Apple");
 
    FruitIterator = find (Fruit.begin(), Fruit.end(), "Pineapple");  //返回值是一个迭代器
    if (FruitIterator == Fruit.end())  cout << "Fruit not found in list" << endl;
    else  cout << *FruitIterator << endl;
}

⑾remove():用remove()算法返回一个指向新的list的结尾的iterator。从开始到这个新的结尾(不含新结尾元素)的范围 包含了remove后剩下所有元素。你可以用list成员函数erase函数来删除从新结尾到老结尾的部分。一共有两种remove

#include <string> 
#include <list>
#include <algorithm>
PrintIt(string& AString) { cout << AString << endl; }
int main (void)
{
    list<string> Birds;
    list<string>::iterator NewEnd;
    Birds.push_back("cockatoo");
    Birds.push_back("galah");
    Birds.push_back("cockatoo");
    Birds.push_back("rosella");
    Birds.push_back("king parrot");
    cout << "Original list" << endl;
    for_each(Birds.begin(), Birds.end(), PrintIt);
    NewEnd = remove(Birds.begin(), Birds.end(), "cockatoo");  //最后一个输入要删除的元素,返回新的结尾迭代器
    cout << endl << "List according to new past the end iterator" << endl;
    for_each(Birds.begin(), NewEnd, PrintIt);
    cout << endl << "Original list now. Care required!" << endl;
    for_each(Birds.begin(), Birds.end(), PrintIt);
}

#include <string>  //
#include <list>
#include <algorithm>
PrintIt (const string& StringToPrint)
{
cout << StringToPrint << endl;
}
 
int main (void)
{
list<string> Birds;
Birds.push_back("cockatoo");
Birds.push_back("galah");
Birds.push_back("cockatoo");
Birds.push_back("rosella");
Birds.push_back("corella");
cout << "Original list with cockatoos" << endl;
for_each(Birds.begin(), Birds.end(), PrintIt);
Birds.remove("cockatoo");
cout << "Now no cockatoos" << endl;
for_each(Birds.begin(), Birds.end(), PrintIt);
}


⑿insert() :

#include <list>
 
int main (void)
{
    list<int> list1;
    for (int i = 0; i < 10; ++i) list1.push_back(i);
    list1.insert(list1.begin(), -1);
    list1.insert(list1.end(), 10);
    int IntArray[2] = {11,12};
    list1.insert(list1.end(), &IntArray[0], &IntArray[2]);
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值