数据结构与算法--单链表

238 阅读15分钟

对于⾮非空的线性表和线性结构,其特点如下:

  • 存在唯⼀一的⼀一个被称作”第⼀一个”的数据元素;
  • 存在唯⼀一的⼀一个被称作”最后⼀一个"的数据元素
  • 除了了第⼀一个之外,结构中的每个数据元素均有⼀一个前驱
  • 除了了最后⼀一个之外,结构中的每个数据元素都有⼀一个后继.

1 顺序表

c语言实现

#include <stdio.h>
#include "stdlib.h"
#include "math.h"
#include "time.h"

#define MAXSIZE 100
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

/* ElemType类型根据实际情况而定,这里假设为int */
typedef int ElemType;
/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Status;
/*线性结构使用顺序表的方式存储*/
//顺序表结构设计
typedef struct {
    ElemType *data;
    int length;
}Sqlist;

// 1 顺序表初始化
Status InitList(Sqlist *L) {
    //为顺序表分配一个大小为MAXSIZE 的数组空间
    L->data =  malloc(sizeof(ElemType) * MAXSIZE);
    //存储分配失败退出
    if(!L->data) exit(ERROR);
    //空表长度为0
    L->length = 0;
    return OK;
}

// 2 顺序表的插入
/*
 初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
 */
Status ListInsert(Sqlist *L,int i,ElemType e) {
    //i值不合法判断
    if((i<1) || (i>L->length+1)) return ERROR;
    //存储空间已满
    if(L->length == MAXSIZE) return ERROR;
    //插入数据不在表尾,则先移动出空余位置
    if(i <= L->length){
        for(int j = L->length-1; j>=i-1;j--){
            //插入位置以及之后的位置后移动1位
            L->data[j+1] = L->data[j];
        }
    }
    //将新元素e 放入第i个位置上
    L->data[i-1] = e;
    //长度+1;
    ++L->length;
    return OK;
}

// 3 顺序表的取值
Status GetElem(Sqlist L,int i, ElemType *e) {
    //判断i值是否合理, 若不合理,返回ERROR
    if(i<1 || i > L.length) return  ERROR;
    //data[i-1]单元存储第i个数据元素.
    *e = L.data[i-1];
    return OK;
}

// 4 顺序表删除
/*
 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
 操作结果: 删除L的第i个数据元素,L的长度减1
 */
Status ListDelete(Sqlist *L,int i) {
    //线性表为空
    if(L->length == 0) return ERROR;
    //i值不合法判断
    if((i<1) || (i>L->length+1)) return ERROR;
    for(int j = i; j < L->length;j++){
        //被删除元素之后的元素向前移动
        L->data[j-1] = L->data[j];
    }
    //表长度-1;
    L->length --;
    return OK;
    
}

// 5 清空顺序表
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Status ClearList(Sqlist *L) {
    L->length=0;
    return OK;
}

// 6 判断顺序表清空
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(Sqlist L) {
    if(L.length==0)
        return TRUE;
    else
        return FALSE;
}

// 7 获取顺序表长度ListEmpty元素个数 */
int ListLength(Sqlist L) {
    return L.length;
}

// 8 顺序输出List
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status TraverseList(Sqlist L) {
    int i;
    for(i=0;i<L.length;i++)
        printf("%d",L.data[i]);
    printf("\n");
    return OK;
}

// 9 顺序表查找元素并返回位置
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int LocateElem(Sqlist L,ElemType e) {
    int i;
    if (L.length==0) return 0;
    
    for(i=0;i<L.length;i++)
    {
        if (L.data[i]==e)
            break;
    }
  
    if(i>=L.length) return 0;
    return i+1;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    Sqlist L;
    ElemType e;
    Status iStatus;
    //1.1 顺序表初始化
    iStatus = InitList(&L);
    printf("初始化L后: L.Length = %d\n", L.length);
    //1.2 顺序表数据插入
    for(int j=1; j <= 5;j++){
        iStatus = ListInsert(&L, 1, j);
    }
    printf("插入数据L长度: %d\n",L.length);
    //1.3 顺序表取值
    GetElem(L, 5, &e);
    printf("顺序表L第5个元素的值为:%d\n",e);
    //1.4 顺序表删除第2个元素
    ListDelete(&L, 2);
    printf("顺序表删除第%d元素,长度为%d\n",2,L.length);
    //1.5 清空顺序表
    iStatus = ClearList(&L);
    printf("清空后,L.length = %d\n",L.length);
    //1.6 判断List是否为空
    iStatus=ListEmpty(L);
    printf("L是否空:i=%d(1:是 0:否)\n",iStatus);
    //1.8 TraverseList
    for(int j=1; j <= 5;j++){
        iStatus = ListInsert(&L, 1, j);
    }
    TraverseList(L);
    
    return 0;
}
//打印
//初始化L后: L.Length = 0
//插入数据L长度: 5
//顺序表L第5个元素的值为:1
//顺序表删除第2元素,长度为4
//清空后,L.length = 0
//L是否空:i=1(1:是 0:否)
//54321

swift 实现

let MAXSIZE = 20
// 顺序表结构设计
struct List<T:Equatable> {
    var data = [T?](repeating: nil, count: MAXSIZE);
    var length = 0;
    // 2 顺序表的插入
    /*
     初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
     操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
     */
    mutating func insert(i:Int, e:T) -> Bool {
        // i值不合法判断
        if i < 1 && i > length + 1 && length >= MAXSIZE {
            return false;
        }
        // 插入数据不在表尾,则先移动出空余位置
        if i < length+1 {
            var index = length
            while index >= i - 1 {
                data[index+1] = data[index];
                index -= 1;
            }
        }
        // 将新元素e 放入第i个位置上
        data[i-1] = e;
        // 长度+1;
        length += 1;
        return true;
    }
    // 顺序表的取值
    func getValue(_ i:Int) -> T? {
        //判断i值是否合理, 若不合理,返回nil
        if length == 0 || i < 1 || i > length {
            return nil;
        }
        return data[i-1];
    }
    // 顺序表删除
    /*
     初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
     操作结果: 删除L的第i个数据元素,L的长度减1
     */
    mutating func delete(_ i:Int) -> T? {
        // 判断i值是否合理, 若不合理,返回nil
        if length == 0 || i < 1 || i > length + 1 {
            return nil;
        }
        let temp = data[i-1];
        // 被删除元素之后的元素向前移动
        for index in i - 1 ..< length {
            data[index] = data[index+1]
        }
        // 表长度-1;
        length -= 1;
        return temp;
    }
    // 清空顺序表
    mutating func clear() -> Bool {
        length = 0;
        return true;
    }
    // 判断顺序表清空
    /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
    func isEmpty() -> Bool {
        return length == 0;
    }
    
    // 获取顺序表长度List元素个数
    func listLength() -> Int {
        return length;
    }
    
    // 顺序表查找元素并返回位置
    /* 初始条件:顺序线性表L已存在 */
    /* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
    /* 若这样的数据元素不存在,则返回值为0 */
    func select(_ e:T) -> Int {
        if length == 0 {
            return 0;
        }
        var i = 0;
        for index in 0 ... length {
            if let temp = data[index] {
                if temp == e {
                    i = index;
                    break;
                }
            }
        }
        return i + 1;
    }
}

extension List : CustomStringConvertible {
    var description: String {
        return "data"+String(describing: data[0...length-1])+"length:\(length)"
    }
}

//1 顺序表初始化
var l = List<Int>()
print("初始化L后: L.Length = \(l.listLength())");

//2 顺序表数据插入
for index in 1 ... 5 {
    l.insert(i: 1, e: index);
}
print("插入数据L长度: \(l.listLength())");
//3 顺序表取值
print("顺序表L第5个元素的值为:\(l.getValue(5))");
//4 顺序表删除第2个元素
print("顺序表删除第2元素:\(l.delete(2)),长度为\(l.listLength())");
//5 清空顺序表
print("是否清空表\(l.clear()),长度为\(l.listLength())");
//6 判断List是否为空
print("L是否空:\(l.isEmpty())");

//8 遍历
for index in 1 ... 5 {
    l.insert(i: 1, e: index);
}
print(l);

//打印
//初始化L后: L.Length = 0
//插入数据L长度: 5
//顺序表L第5个元素的值为:Optional(1)
//顺序表删除第2元素:Optional(4),长度为4
//是否清空表true,长度为0
//L是否空:true
//data[Optional(5), Optional(4), Optional(3), Optional(2), Optional(1)]length:5

2 单链表

单链表
c 实现

#include <stdio.h>
#include "string.h"
#include "ctype.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"

#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OK 1

#define MAXSIZE 20 /* 存储空间初始分配量 */

typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */

//定义结点
typedef struct Node {
    ElemType data;
    struct Node *next;
}Node;

typedef struct Node * LinkList;

// 1 初始化单链表线性表
Status InitList(LinkList *L) {
    //产生头结点,并使用L指向此头结点
    *L = (LinkList)malloc(sizeof(Node));
    //存储空间分配失败
    if(*L == NULL) return ERROR;
    //将头结点的指针域置空
    (*L)->next = NULL;
    return OK;
}

// 2 单链表插入
/*
 初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
 操作结果:在L中第i个位置之后插入新的数据元素e,L的长度加1;
 */
Status ListInsert(LinkList *L,int i,ElemType e) {
    int j;
    LinkList p,s;
    p = *L;
    j = 1;
    //寻找第i-1个结点
    while (p && j<i) {
        p = p->next;
        ++j;
    }
    //第i个元素不存在
    if(!p || j>i) return ERROR;
    //生成新结点s
    s = (LinkList)malloc(sizeof(Node));
    //将e赋值给s的数值域
    s->data = e;
    //将p的后继结点赋值给s的后继
    s->next = p->next;
    //将s赋值给p的后继
    p->next = s;
    return OK;
}
// 3 单链表取值
/*
 初始条件: 顺序线性表L已存在,1≤i≤ListLength(L);
 操作结果:用e返回L中第i个数据元素的值
 */
Status GetElem(LinkList L,int i,ElemType *e) {
    //j: 计数.
    int j;
    //声明结点p;
    LinkList p;
    //将结点p 指向链表L的第一个结点;
    p = L->next;
    //j计算=1;
    j = 1;
    //p不为空,且计算j不等于i,则循环继续
    while (p && j<i) {
        //p指向下一个结点
        p = p->next;
        ++j;
    }
    //如果p为空或者j>i,则返回error
    if(!p || j > i) return ERROR;
    //e = p所指的结点的data
    *e = p->data;
    return OK;
}

// 4 单链表删除元素
/*
 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1
 */
Status ListDelete(LinkList *L,int i,ElemType *e) {
    int j;
    LinkList p,q;
    p = (*L)->next;
    j = 1;
    //查找第i-1个结点,p指向该结点
    while (p->next && j<(i-1)) {
        p = p->next;
        ++j;
    }
    //当i>n 或者 i<1 时,删除位置不合理
    if (!(p->next) || (j>i-1)) return  ERROR;
    //q指向要删除的结点
    q = p->next;
    //将q的后继赋值给p的后继
    p->next = q->next;
    //将q结点中的数据给e
    *e = q->data;
    //让系统回收此结点,释放内存;
    free(q);
    return OK;
}

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status ListTraverse(LinkList L) {
    LinkList p=L->next;
    while(p)
    {
        printf("%d",p->data);
        p=p->next;
    }
    printf("\n");
    return OK;
}

/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Status ClearList(LinkList *L) {
    LinkList p,q;
    p=(*L)->next;           /*  p指向第一个结点 */
    /*  没到表尾 */
    while(p) {
        q = p->next;
        free(p);
        p=q;
    }
    (*L)->next = NULL;        /* 头结点指针域为空 */
    return OK;
}

// 单链表前插入法
/* 随机产生n个元素值,建立带表头结点的单链线性表L(前插法)*/
void CreateListHead(LinkList *L, int n) {
    LinkList p;
    //建立1个带头结点的单链表
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;
    //循环前插入随机数据
    for(int i = 0; i < n;i++) {
        //生成新结点
        p = (LinkList)malloc(sizeof(Node));
        //i赋值给新结点的data
        p->data = i;
        //p->next = 头结点的L->next
        p->next = (*L)->next;
        //将结点P插入到头结点之后;
        (*L)->next = p;
    }
}

// 单链表后插入法
/* 随机产生n个元素值,建立带表头结点的单链线性表L(后插法)*/
void CreateListTail(LinkList *L, int n) {
    LinkList p,r;
    //建立1个带头结点的单链表
    *L = (LinkList)malloc(sizeof(Node));
    //r指向尾部的结点
    r = *L;
    for (int i=0; i<n; i++) {
        //生成新结点
        p = (Node *)malloc(sizeof(Node));
        p->data = i;
        //将表尾终端结点的指针指向新结点
        r->next = p;
        //将当前的新结点定义为表尾终端结点
        r = p;
    }
    //将尾指针的next = null
    r->next = NULL;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    Status iStatus;
    LinkList L1,L;
    struct Node *L2;
    ElemType e;
    
    //2.1 单链表初始化
    iStatus = InitList(&L);
    printf("L 是否初始化成功?(0:失败,1:成功) %d\n",iStatus);
    
    //2.2 单链表插入数据
    for(int j = 1;j<=10;j++) {
        iStatus = ListInsert(&L, 1, j);
    }
    printf("L 插入后\n");
    ListTraverse(L);
    
    //2.3 单链表获取元素
    GetElem(L,5,&e);
    printf("第5个元素的值为:%d\n",e);
    
    //2.4 删除第5个元素
    iStatus = ListDelete(&L, 5, &e);
    printf("删除第5个元素值为:%d\n",e);
    ListTraverse(L);
    
    //3.1 前插法整理创建链表L
    iStatus = ClearList(&L);
    CreateListHead(&L, 20);
    printf("整理创建L的元素(前插法):\n");
    ListTraverse(L);
    
    //3.2 后插法整理创建链表L
    iStatus = ClearList(&L);
    CreateListTail(&L, 20);
    printf("整理创建L的元素(后插法):\n");
    ListTraverse(L);
    
}
//打印
//L 是否初始化成功?(0:失败,1:成功) 1
//L 插入后
//10987654321
//第5个元素的值为:6
//删除第5个元素值为:6
//1098754321
//整理创建L的元素(前插法):
//191817161514131211109876543210
//整理创建L的元素(后插法):
//012345678910111213141516171819

swift 实现

//定义结点
class Node<T> {
    var data:T?
    var next:Node?
    // 单链表插入
    /*
     初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
     操作结果:在L中第i个位置之后插入新的数据元素e,L的长度加1;
     */
    func insert(i:Int, e:T) -> Bool {
        // 条件判断
        if i < 1 && i > length() + 1 {
            return false
        }
        var temp:Node? = self
        var index = 0;
        // 寻找第i-1个结点
        while temp != nil && index < i - 1 {
            temp = temp?.next
            index += 1;
        }
        // 第i-1个元素不存在
        if temp == nil { return false }
        //生成新结点s
        let s = Node<T>()
        // 将e赋值给s的数值域
        s.data = e
        //将temp的后继结点赋值给s的后继
        s.next = temp?.next;
        //将s赋值给temp的后继
        temp?.next = s
        return true;
    }
    
    // 单链表取值
    /*
     初始条件: 顺序线性表L已存在,1≤i≤ListLength(L);
     操作结果:用e返回L中第i个数据元素的值
     */
    func getValue(_ i:Int) -> T? {
        // 条件判断
        if i < 1 && i > length() + 1 {
            return nil
        }
        // 获取第i个节点
        var index = 1;
        var temp = next
        // temp不为空,且计算index小于i,则循环继续
        while temp != nil && index < i {
            temp = temp?.next
            index += 1
        }
        // 返回结点的data
        return temp?.data;
    }
    
    // 单链表删除元素
    /*
     初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
     操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1
     */
    func delete(_ i:Int) -> T? {
        // 条件判断
        if i < 1 && i > length() + 1 {
            return nil
        }
        // 查找第i-1个结点,temp指向该结点
        var index = 0;
        var temp:Node? = self
        while temp != nil && index < i - 1 {
            temp = temp?.next
            index += 1
        }
        //当temp不存在 时,返回nil
        if temp == nil {return nil}
        let value = temp?.next?.data;
        //将temp的后继的后继赋值给temp的后继
        temp?.next = temp?.next?.next;
        return value;
    }
    // 清空链表
    /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
    func clear() -> Bool {
        next = nil;
        return true;
    }
    
    // 单链表前插入法
    /* 随机产生n个元素值,建立带表头结点的单链线性表L(前插法)*/
    static func createHead(_ n:Int) -> Node<Int> {
        let s = Node<Int>()
        for index in 1 ... n {
            let a = Node<Int>()
            a.data = index;
            let temp = s.next;
            a.next = temp;
            s.next = a;
        }
        return s
    }
    
    // 单链表后插入法
    /* 随机产生n个元素值,建立带表头结点的单链线性表L(后插法)*/
    static func createTail(_ n:Int) -> Node<Int> {
        let s = Node<Int>()
        var r = s
        for index in 1 ... n {
        let a = Node<Int>()
            a.data = index
            r.next = a
            r = a;
        }
        return s
    }
    
    func length() -> Int {
        var temp = next
        var lenght = 0;
        while temp != nil {
            temp = temp?.next;
            lenght += 1;
        }
        return lenght
    }
    
    deinit {
        print("节点销毁\(String(describing: data))")
    }
}

extension Node : CustomStringConvertible {
    var description: String {
        guard let next = next else {
            if data == nil {
                return "头结点"
            }
            return "\(String(describing: data))"
        }
        if data == nil {
            return String(describing: next)
        }
        return "\(String(describing: data)) -> " + String(describing: next)
    }
}

func main()->Void {
    //1 单链表初始化
    let l = Node<Int>()
    print(l)

    //2 单链表插入数据
    for index in 1 ... 10 {
        l.insert(i: 1, e: index)
    }
    print("L 插入后")
    print(l)

    //3 单链表获取元素
    print("第5个元素的值为:\(l.getValue(5))")

    //2.4 删除第5个元素
    print("删除第5个元素值为:\(l.delete(5))");
    print(l)
    print("是否清空\(l.clear()) 打印\(l)")
    // 前插法整理创建链表L
    let b = Node<Int>.createHead(20)
    print("整理创建b的元素(前插法):");
    print(b);

    // 后插法整理创建链表L
    let c = Node<Int>.createTail(20)
    print("整理创建c的元素(后插法):");
    print(c);
}
main()

//打印
//头结点
//L 插入后
//Optional(10) -> Optional(9) -> Optional(8) -> Optional(7) -> Optional(6) -> Optional(5) -> Optional(4) -> Optional(3) -> Optional(2) -> Optional(1)
//第5个元素的值为:Optional(6)
//节点销毁Optional(6)
//删除第5个元素值为:Optional(6)
//Optional(10) -> Optional(9) -> Optional(8) -> Optional(7) -> Optional(5) -> Optional(4) -> Optional(3) -> Optional(2) -> Optional(1)
//是否清空true 打印头结点
//整理创建b的元素(前插法):
//Optional(20) -> Optional(19) -> Optional(18) -> Optional(17) -> Optional(16) -> Optional(15) -> Optional(14) -> Optional(13) -> Optional(12) -> Optional(11) -> Optional(10) -> Optional(9) -> Optional(8) -> Optional(7) -> Optional(6) -> Optional(5) -> Optional(4) -> Optional(3) -> Optional(2) -> Optional(1)
//整理创建c的元素(后插法):
//Optional(1) -> Optional(2) -> Optional(3) -> Optional(4) -> Optional(5) -> Optional(6) -> Optional(7) -> Optional(8) -> Optional(9) -> Optional(10) -> Optional(11) -> Optional(12) -> Optional(13) -> Optional(14) -> Optional(15) -> Optional(16) -> Optional(17) -> Optional(18) -> Optional(19) -> Optional(20)