zoukankan      html  css  js  c++  java
  • 一窥--顺序表和单链表

    顺序表和单链表

    真正意义上自己弄出来的,发篇博客记录一下

    顺序表

    类似于数组,元素都是相邻的,这也决定了它比较容易和比较适合查询。但缺点就是长度有限。

    时间复杂度

    • 查询操作 O(1)
    • 插入和删除操作 O(n)

    代码实现

    #include<iostream>
    #include<string>
    using namespace std;
    const int MAXSIZE = 20; //线性表最大长度 
    
    typedef int ElemType;
    typedef struct{
    	ElemType data[MAXSIZE];
    	int length; //线性表长度 
    	
    } Sqlist;
    
    //按照1,2,...,n进行计数 
    void SetElem(Sqlist &L){
    	for (int i=0;i<L.length;i++)
    		L.data[i] = i+1;
    }
    
    int GetElem(Sqlist L,int i){
    	if(L.length == 0 || i<1 || i>L.length)
    		return -1;
    	return L.data[i-1];
    }
    
    string ListInsert(Sqlist *L,int index,ElemType num){
    	if( L->length == MAXSIZE)
    		return "List is already full";
    	if(index<1 || index>=L->length+1)
    		return "Index is out of range";
    	if(index<=L->length){
    		int k;
    		//元素后移 
    		for (k=L->length-1;k>=index-1;k--){
    			//error这样长度不变:L->data[k] = L->data[k-1];
    			L->data[k+1] = L->data[k];
    		}
    		L->data[index-1] = num;
    		L->length++;
    		return "Inserted!";
    	}
    }
    
    string ListDelete(Sqlist *L,int index){
    	if (L->length==0)
    		return "List is empty";
    	if (index<1 || index >L->length)
    		return "Index is out of range";
    	if (index<=L->length){
    		int k;
    		for (k=index-1;k<L->length-1;k++)
    			L->data[k] = L->data[k+1];
    		L->length--;
    		return "Deleted!";
    	}
    }
    int main(){
    	Sqlist sq;
    	sq.length = 10;
    	
    	SetElem(sq);
    	
    	cout<<ListInsert(&sq,10,100)<<endl;
    	
    	for (int i=0;i<sq.length;i++)
    		cout<<GetElem(sq,i+1)<<" ";
    	cout<< endl;
    	
    	cout<<ListDelete(&sq,1)<<endl;
    	for (int i=0;i<sq.length;i++)
    		cout<<GetElem(sq,i+1)<<" ";
    	cout<< endl;
    	return 0;
    }
    

    缺点

    1. 长度有限,不灵活
    2. 查询和删除操作太慢
    3. 会有多余的空间被浪费 :MAXSIZE-length
    4. 当改变长度时候,内存可能需要进行大面积的数值迁移,浪费内存资源

    单链表

    长度随心,非常灵活,创建麻烦些,但是一劳永逸

    组成:结点

    1. 数据域:存储数据元素信息的域
    2. 指针域:存储直接后继位置的域
    3. 头指针:标志作用,无论链表是否为空,它不为空。且位于第一个元素之前,它的数据域一般无意义(可以用来存放链表长度)。

    时间复杂度

    • 查询操作:O(n)
    • 插入/删除操作:O(1)

    代码实现

    #include<iostream>
    #include<string>
    using namespace std;
    
    typedef int ElemType;
    struct Node{
    	ElemType data;//数据域 node->data
    	struct Node *next;//指针域 node->next
    }; 
    string CreateListHead(Node *L){//L是现在是空表的头指针 
    	L->next = NULL;//头结点初始化 
    	Node *p = new Node;
    	if(!p)
    		return "Create fail";
    	cin>>p->data;
    	while(p->data){//当输入为0,停止创建 
    		p->next = L->next;
    		L->next = p;
    		p = new Node;
    		cin>>p->data;
    	}
    	delete p;
    	return "Create list from head!"; 
    }
    
    string CreateListTail(Node *L){
    	L->next = NULL;
    	Node *p = new Node;
    	Node *t = L;//指向尾结点 
    	if(!p)
    		return "Create fail (from tail)";
    	cin>>p->data;
    	while(p->data){
    		t->next = p;
    		t = p;
    		p = new Node;
    		cin>>p->data;
    	}
    	t->next = NULL;//最后指向NULL 
    	delete p;
    	return "Create list from tail!";
    }
    
    int GetElem(Node *L,int index){
    	int j=1;
    	Node *p = new Node;
    	p = L->next;//指向头结点 
    	while(p && j<index){
    		p = p->next;
    		j++;
    	}	
    	//p&&j<i 条件取反 
    	if (!p){
    		return -1;
    	}
    	return p->data;
    }
    
    string ListInsert(Node *L,int index,ElemType e){
    	int j;
    	Node *p,*s;
    	p = new Node;
    	s = new Node;
    	if(!p && !s)
    		return "Insert fail";
    	p = L; //注意插入操作,体现头结点的好处:统一处理的代码 
    	j = 1;
    	while(p && j<index){
    		p = p->next;
    		j++;
    	}
    	if (!p)
    		return "Index out of change";
    	
    	s->data = e;
    	s->next = p->next;
    	p->next = s;
    	//这里p和s不能删除 
    	return "Inserted!";
    }
    
    string ListDelete(Node *L,int index,ElemType e){
    	int j;
    	Node *p,*s= new Node;
    	p = L;//p指向头 
    	j = 1;
    	while(p->next && j<index){ //p->next 是要删除的,这样,p就保存了删除的结点前一个结点的信息 
    		p = p->next;
    		++j;
    	}
    	if(!(p->next)){
    		return "Index out of change";
    	}
    	
    	s = p->next;
    	p->next = s->next;
    	
    	delete s; //删除结点 
    	return "Deleted!";
    }
    
    void ShowList(Node *L){
    	Node *p = L->next;
    	if(!p)
    		cout<<"List is empty"<<endl;
    	while(p){
    		cout<<p->data<<" ";
    		p = p->next;
    	}
    	cout<<endl;
    }
    int main(){
    	
    	Node *node = new Node;
    	CreateListHead(node); //头插法,倒着插入 ,1,2,3
    	ShowList(node);
    	cout<<ListInsert(node,2,-10)<<endl;
    	ShowList(node);
    
    	Node *_node = new Node;
    	CreateListTail(_node);
    	ShowList(_node);
    	cout<<ListInsert(_node,2,-10)<<endl;
    	ShowList(_node);
    	
    	delete node;
    	delete _node;
    	return 0;
    }
    

    缺点

    1. 查询消耗时间
    2. 在中间位置插入时候,时间复杂度大
  • 相关阅读:
    sql性能查询
    ASP.Net Web应用程序与EXCEL交互时遇到的权限问题
    Connection strings for Excel 2007
    获取异常的具体出处dbms_utility.format_error_backtrace
    C#获取Excel架构信息的方法
    Oracle强杀进程
    C#游标溢出(访问数据库)解决方案。
    Visual C# 2008 调试技巧一
    【POI】修改Excel内容
    【Eclipse】在Eclipse工具中自定义类注释
  • 原文地址:https://www.cnblogs.com/AsuraDong/p/single_list.html
Copyright © 2011-2022 走看看