6.2单链表

来源:互联网 发布:电影源码带采集 编辑:程序博客网 时间:2024/05/22 00:44

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
原创粉丝点击